WebKit Bugzilla
Attachment 350127 Details for
Bug 189725
: [EME] Introduce the concept of CDMInstanceSession.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-189725-20180919095350.patch (text/plain), 78.67 KB, created by
Jer Noble
on 2018-09-19 09:53:51 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Jer Noble
Created:
2018-09-19 09:53:51 PDT
Size:
78.67 KB
patch
obsolete
>Subversion Revision: 236078 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index a99a5e4b5c84a4f6b8430837b3a5c31e70908f08..14cd2b025dbd898c65e6747e435c907ebc6eaeaa 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,119 @@ >+2018-09-18 Jer Noble <jer.noble@apple.com> >+ >+ [EME] Introduce the concept of CDMInstanceSession. >+ https://bugs.webkit.org/show_bug.cgi?id=189725 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Currently, the same CDMInstance owned by a MediaKeys object is passed to every MediaKeySession created by that >+ MediaKeys, and since the CDMInstance has only a single CDMInstanceClient, subsequent MediaKeySessions prevent >+ previous ones from getting updates. >+ >+ Add a new virtual interface, CDMInstanceSession, to be passed to MediaKeySession upon creation. Refactor >+ CDMInstanceClearKey and CDMInstanceFairPlayStreamingAVFObjC to adopt this new interface. >+ >+ * Modules/encryptedmedia/MediaKeySession.cpp: >+ (WebCore::MediaKeySession::create): >+ (WebCore::MediaKeySession::MediaKeySession): >+ (WebCore::MediaKeySession::generateRequest): >+ (WebCore::MediaKeySession::load): >+ (WebCore::MediaKeySession::update): >+ (WebCore::MediaKeySession::remove): >+ (WebCore::MediaKeySession::updateKeyStatuses): >+ * Modules/encryptedmedia/MediaKeySession.h: >+ * Modules/encryptedmedia/MediaKeys.cpp: >+ (WebCore::MediaKeys::createSession): >+ * WebCore.xcodeproj/project.pbxproj: >+ * platform/encryptedmedia/CDMInstance.h: >+ (WebCore::CDMInstance::setHDCPStatus): >+ (WebCore::CDMInstance::setClient): Deleted. >+ (WebCore::CDMInstance::clearClient): Deleted. >+ * platform/encryptedmedia/CDMInstanceSession.h: Copied from Source/WebCore/platform/encryptedmedia/CDMInstance.h. >+ (WebCore::CDMInstanceSession::setClient): >+ (WebCore::CDMInstanceSession::clearClient): >+ * platform/encryptedmedia/clearkey/CDMClearKey.cpp: >+ (WebCore::parseLicenseFormat): >+ (WebCore::CDMInstanceClearKey::keySystem const): >+ (WebCore::CDMInstanceClearKey::createSession): >+ (WebCore::CDMInstanceSessionClearKey::requestLicense): >+ (WebCore::CDMInstanceSessionClearKey::keys const): >+ (WebCore::CDMInstanceSessionClearKey::updateLicense): >+ (WebCore::CDMInstanceSessionClearKey::loadSession): >+ (WebCore::CDMInstanceSessionClearKey::closeSession): >+ (WebCore::CDMInstanceSessionClearKey::removeSessionData): >+ (WebCore::CDMInstanceSessionClearKey::storeRecordOfKeyUsage): >+ (WebCore::CDMInstanceClearKey::requestLicense): Deleted. >+ (WebCore::CDMInstanceClearKey::keys const): Deleted. >+ (WebCore::CDMInstanceClearKey::updateLicense): Deleted. >+ (WebCore::CDMInstanceClearKey::loadSession): Deleted. >+ (WebCore::CDMInstanceClearKey::closeSession): Deleted. >+ (WebCore::CDMInstanceClearKey::removeSessionData): Deleted. >+ (WebCore::CDMInstanceClearKey::storeRecordOfKeyUsage): Deleted. >+ * platform/encryptedmedia/clearkey/CDMClearKey.h: >+ * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h: >+ * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm: >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::createSession): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::processContentKeyRequestForSession): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::processNextContentKeyRequest): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::keySystem const): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::keyIDs): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::loadSession): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::storeRecordOfKeyUsage): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::setClient): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::clearClient): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRequest): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRenewingRequest): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvidePersistableRequest): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didFailToProvideRequest): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestDidSucceed): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::shouldRetryRequestForReason): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::sessionIdentifierChanged): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged): >+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::isLicenseTypeSupported const): >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::isLicenseTypeSupported const): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::keyIDs): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestLicense): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::updateLicense): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::loadSession): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::closeSession): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::removeSessionData): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::storeRecordOfKeyUsage): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::setClient): Deleted. >+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::clearClient): Deleted. >+ * testing/MockCDMFactory.cpp: >+ (WebCore::MockCDMInstance::keySystem const): >+ (WebCore::MockCDMInstance::createSession): >+ (WebCore::MockCDMInstanceSession::MockCDMInstanceSession): >+ (WebCore::MockCDMInstanceSession::requestLicense): >+ (WebCore::MockCDMInstanceSession::updateLicense): >+ (WebCore::MockCDMInstanceSession::loadSession): >+ (WebCore::MockCDMInstanceSession::closeSession): >+ (WebCore::MockCDMInstanceSession::removeSessionData): >+ (WebCore::MockCDMInstanceSession::storeRecordOfKeyUsage): >+ (WebCore::MockCDMInstance::requestLicense): Deleted. >+ (WebCore::MockCDMInstance::updateLicense): Deleted. >+ (WebCore::MockCDMInstance::loadSession): Deleted. >+ (WebCore::MockCDMInstance::closeSession): Deleted. >+ (WebCore::MockCDMInstance::removeSessionData): Deleted. >+ (WebCore::MockCDMInstance::storeRecordOfKeyUsage): Deleted. >+ * testing/MockCDMFactory.h: >+ (WebCore::MockCDMInstance::factory const): >+ (WebCore::MockCDMInstance::distinctiveIdentifiersAllowed const): >+ (WebCore::MockCDMInstance::persistentStateAllowed const): >+ > 2018-09-18 Jer Noble <jer.noble@apple.com> > > REGRESSION (r236006): New waitingForKey() requirement breaks Modern EME tests. >diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp >index eb72ce0778e81cbbcfbeba434c7828dd9a1152a4..68f493d5d10625eb5ff108edfb8c392d884d41ac 100644 >--- a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp >+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp >@@ -48,14 +48,14 @@ > > namespace WebCore { > >-Ref<MediaKeySession> MediaKeySession::create(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance) >+Ref<MediaKeySession> MediaKeySession::create(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstanceSession>&& instance) > { > auto session = adoptRef(*new MediaKeySession(context, WTFMove(keys), sessionType, useDistinctiveIdentifier, WTFMove(implementation), WTFMove(instance))); > session->suspendIfNeeded(); > return session; > } > >-MediaKeySession::MediaKeySession(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance) >+MediaKeySession::MediaKeySession(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstanceSession>&& instance) > : ActiveDOMObject(&context) > , m_keys(WTFMove(keys)) > , m_expiration(std::numeric_limits<double>::quiet_NaN()) >@@ -88,7 +88,7 @@ MediaKeySession::MediaKeySession(ScriptExecutionContext& context, WeakPtr<MediaK > UNUSED_PARAM(m_closed); > UNUSED_PARAM(m_uninitialized); > >- m_instance->setClient(*this); >+ m_instance->setClient(m_cdmInstanceClientWeakPtrFactory.createWeakPtr(*this)); > } > > MediaKeySession::~MediaKeySession() >@@ -194,7 +194,7 @@ void MediaKeySession::generateRequest(const AtomicString& initDataType, const Bu > m_latestDecryptTime = 0; > } > >- m_instance->requestLicense(m_sessionType, initDataType, WTFMove(initData), [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, CDMInstance::SuccessValue succeeded) mutable { >+ m_instance->requestLicense(m_sessionType, initDataType, WTFMove(initData), [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, CDMInstanceSession::SuccessValue succeeded) mutable { > if (!weakThis) > return; > >@@ -217,7 +217,7 @@ void MediaKeySession::generateRequest(const AtomicString& initDataType, const Bu > // 10.10. Queue a task to run the following steps: > m_taskQueue.enqueueTask([this, promise = WTFMove(promise), message = WTFMove(message), messageType, sessionId, succeeded] () mutable { > // 10.10.1. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name. >- if (succeeded == CDMInstance::SuccessValue::Failed) { >+ if (succeeded == CDMInstanceSession::SuccessValue::Failed) { > promise->reject(NotSupportedError); > return; > } >@@ -287,7 +287,7 @@ void MediaKeySession::load(const String& sessionId, Ref<DeferredPromise>&& promi > // 8.6. Let message type be null. > // 8.7. Let cdm be the CDM instance represented by this object's cdm instance value. > // 8.8. Use the cdm to execute the following steps: >- m_instance->loadSession(m_sessionType, *sanitizedSessionId, origin, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise), sanitizedSessionId = *sanitizedSessionId] (std::optional<CDMInstance::KeyStatusVector>&& knownKeys, std::optional<double>&& expiration, std::optional<CDMInstance::Message>&& message, CDMInstance::SuccessValue succeeded, CDMInstance::SessionLoadFailure failure) mutable { >+ m_instance->loadSession(m_sessionType, *sanitizedSessionId, origin, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise), sanitizedSessionId = *sanitizedSessionId] (std::optional<CDMInstanceSession::KeyStatusVector>&& knownKeys, std::optional<double>&& expiration, std::optional<CDMInstanceSession::Message>&& message, CDMInstanceSession::SuccessValue succeeded, CDMInstanceSession::SessionLoadFailure failure) mutable { > // 8.8.1. If there is no data stored for the sanitized session ID in the origin, resolve promise with false and abort these steps. > // 8.8.2. If the stored session's session type is not the same as the current MediaKeySession session type, reject promise with a newly created TypeError. > // 8.8.3. Let session data be the data stored for the sanitized session ID in the origin. This must not include data from other origin(s) or that is not associated with an origin. >@@ -299,19 +299,19 @@ void MediaKeySession::load(const String& sessionId, Ref<DeferredPromise>&& promi > // 8.8.7.2. Let message type be the appropriate MediaKeyMessageType for the message. > // NOTE: Steps 8.8.1. through 8.8.7. should be implemented in CDMInstance. > >- if (succeeded == CDMInstance::SuccessValue::Failed) { >+ if (succeeded == CDMInstanceSession::SuccessValue::Failed) { > switch (failure) { >- case CDMInstance::SessionLoadFailure::NoSessionData: >+ case CDMInstanceSession::SessionLoadFailure::NoSessionData: > promise->resolve<IDLBoolean>(false); > return; >- case CDMInstance::SessionLoadFailure::MismatchedSessionType: >+ case CDMInstanceSession::SessionLoadFailure::MismatchedSessionType: > promise->reject(TypeError); > return; >- case CDMInstance::SessionLoadFailure::QuotaExceeded: >+ case CDMInstanceSession::SessionLoadFailure::QuotaExceeded: > promise->reject(QuotaExceededError); > return; >- case CDMInstance::SessionLoadFailure::None: >- case CDMInstance::SessionLoadFailure::Other: >+ case CDMInstanceSession::SessionLoadFailure::None: >+ case CDMInstanceSession::SessionLoadFailure::Other: > // In any other case, the session load failure will cause a rejection in the following task. > break; > } >@@ -320,7 +320,7 @@ void MediaKeySession::load(const String& sessionId, Ref<DeferredPromise>&& promi > // 8.9. Queue a task to run the following steps: > m_taskQueue.enqueueTask([this, knownKeys = WTFMove(knownKeys), expiration = WTFMove(expiration), message = WTFMove(message), sanitizedSessionId, succeeded, promise = WTFMove(promise)] () mutable { > // 8.9.1. If any of the preceding steps failed, reject promise with a the appropriate error name. >- if (succeeded == CDMInstance::SuccessValue::Failed) { >+ if (succeeded == CDMInstanceSession::SuccessValue::Failed) { > promise->reject(NotSupportedError); > return; > } >@@ -388,7 +388,7 @@ void MediaKeySession::update(const BufferSource& response, Ref<DeferredPromise>& > // 6.5. Let session closed be false. > // 6.6. Let cdm be the CDM instance represented by this object's cdm instance value. > // 6.7. Use the cdm to execute the following steps: >- m_instance->updateLicense(m_sessionId, m_sessionType, *sanitizedResponse, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (bool sessionWasClosed, std::optional<CDMInstance::KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<CDMInstance::Message>&& message, CDMInstance::SuccessValue succeeded) mutable { >+ m_instance->updateLicense(m_sessionId, m_sessionType, *sanitizedResponse, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (bool sessionWasClosed, std::optional<CDMInstanceSession::KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<CDMInstanceSession::Message>&& message, CDMInstanceSession::SuccessValue succeeded) mutable { > if (!weakThis) > return; > >@@ -414,7 +414,7 @@ void MediaKeySession::update(const BufferSource& response, Ref<DeferredPromise>& > // Process sanitized response, not storing any session data. > // NOTE: Steps 6.7.1. and 6.7.2. should be implemented in CDMInstance. > >- if (succeeded == CDMInstance::SuccessValue::Failed) { >+ if (succeeded == CDMInstanceSession::SuccessValue::Failed) { > promise->reject(TypeError); > return; > } >@@ -450,16 +450,16 @@ void MediaKeySession::update(const BufferSource& response, Ref<DeferredPromise>& > if (message) { > MediaKeyMessageType messageType; > switch (message->first) { >- case CDMInstance::MessageType::LicenseRequest: >+ case CDMInstanceSession::MessageType::LicenseRequest: > messageType = MediaKeyMessageType::LicenseRequest; > break; >- case CDMInstance::MessageType::LicenseRenewal: >+ case CDMInstanceSession::MessageType::LicenseRenewal: > messageType = MediaKeyMessageType::LicenseRenewal; > break; >- case CDMInstance::MessageType::LicenseRelease: >+ case CDMInstanceSession::MessageType::LicenseRelease: > messageType = MediaKeyMessageType::LicenseRelease; > break; >- case CDMInstance::MessageType::IndividualizationRequest: >+ case CDMInstanceSession::MessageType::IndividualizationRequest: > messageType = MediaKeyMessageType::IndividualizationRequest; > break; > } >@@ -538,7 +538,7 @@ void MediaKeySession::remove(Ref<DeferredPromise>&& promise) > // 4.3. Let message type be null. > > // 4.4. Use the cdm to execute the following steps: >- m_instance->removeSessionData(m_sessionId, m_sessionType, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (CDMInstance::KeyStatusVector&& keys, std::optional<Ref<SharedBuffer>>&& message, CDMInstance::SuccessValue succeeded) mutable { >+ m_instance->removeSessionData(m_sessionId, m_sessionType, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (CDMInstanceSession::KeyStatusVector&& keys, std::optional<Ref<SharedBuffer>>&& message, CDMInstanceSession::SuccessValue succeeded) mutable { > if (!weakThis) > return; > >@@ -565,7 +565,7 @@ void MediaKeySession::remove(Ref<DeferredPromise>&& promise) > updateExpiration(std::numeric_limits<double>::quiet_NaN()); > > // 4.5.3. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name. >- if (succeeded == CDMInstance::SuccessValue::Failed) { >+ if (succeeded == CDMInstanceSession::SuccessValue::Failed) { > promise->reject(NotSupportedError); > return; > } >@@ -599,7 +599,7 @@ void MediaKeySession::enqueueMessage(MediaKeyMessageType messageType, const Shar > m_eventQueue.enqueueEvent(WTFMove(messageEvent)); > } > >-void MediaKeySession::updateKeyStatuses(CDMInstanceClient::KeyStatusVector&& inputStatuses) >+void MediaKeySession::updateKeyStatuses(CDMInstanceSession::KeyStatusVector&& inputStatuses) > { > // https://w3c.github.io/encrypted-media/#update-key-statuses > // W3C Editor's Draft 09 November 2016 >@@ -613,21 +613,21 @@ void MediaKeySession::updateKeyStatuses(CDMInstanceClient::KeyStatusVector&& inp > // 4.2.1. Let pair be the pair. > // 4.2.2. Insert an entry for pair's key ID into statuses with the value of pair's MediaKeyStatus value. > >- static auto toMediaKeyStatus = [] (CDMInstance::KeyStatus status) -> MediaKeyStatus { >+ static auto toMediaKeyStatus = [] (CDMInstanceSession::KeyStatus status) -> MediaKeyStatus { > switch (status) { >- case CDMInstance::KeyStatus::Usable: >+ case CDMInstanceSession::KeyStatus::Usable: > return MediaKeyStatus::Usable; >- case CDMInstance::KeyStatus::Expired: >+ case CDMInstanceSession::KeyStatus::Expired: > return MediaKeyStatus::Expired; >- case CDMInstance::KeyStatus::Released: >+ case CDMInstanceSession::KeyStatus::Released: > return MediaKeyStatus::Released; >- case CDMInstance::KeyStatus::OutputRestricted: >+ case CDMInstanceSession::KeyStatus::OutputRestricted: > return MediaKeyStatus::OutputRestricted; >- case CDMInstance::KeyStatus::OutputDownscaled: >+ case CDMInstanceSession::KeyStatus::OutputDownscaled: > return MediaKeyStatus::OutputDownscaled; >- case CDMInstance::KeyStatus::StatusPending: >+ case CDMInstanceSession::KeyStatus::StatusPending: > return MediaKeyStatus::StatusPending; >- case CDMInstance::KeyStatus::InternalError: >+ case CDMInstanceSession::KeyStatus::InternalError: > return MediaKeyStatus::InternalError; > }; > >diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h >index 0d1900e31bc7bd4917e826b610331ec588c95132..8103c41b4c2b1d43e39ef978d33608f05c0ab3be 100644 >--- a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h >+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h >@@ -31,7 +31,7 @@ > #if ENABLE(ENCRYPTED_MEDIA) > > #include "ActiveDOMObject.h" >-#include "CDMInstance.h" >+#include "CDMInstanceSession.h" > #include "DOMPromiseProxy.h" > #include "EventTarget.h" > #include "GenericEventQueue.h" >@@ -52,9 +52,9 @@ class MediaKeyStatusMap; > class MediaKeys; > class SharedBuffer; > >-class MediaKeySession final : public RefCounted<MediaKeySession>, public EventTargetWithInlineData, public ActiveDOMObject, public CanMakeWeakPtr<MediaKeySession>, public CDMInstanceClient { >+class MediaKeySession final : public RefCounted<MediaKeySession>, public EventTargetWithInlineData, public ActiveDOMObject, public CanMakeWeakPtr<MediaKeySession>, public CDMInstanceSessionClient { > public: >- static Ref<MediaKeySession> create(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstance>&&); >+ static Ref<MediaKeySession> create(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstanceSession>&&); > virtual ~MediaKeySession(); > > using RefCounted<MediaKeySession>::ref; >@@ -78,14 +78,14 @@ public: > const Vector<std::pair<Ref<SharedBuffer>, MediaKeyStatus>>& statuses() const { return m_statuses; } > > private: >- MediaKeySession(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstance>&&); >+ MediaKeySession(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstanceSession>&&); > void enqueueMessage(MediaKeyMessageType, const SharedBuffer&); > void updateExpiration(double); > void sessionClosed(); > String mediaKeysStorageDirectory() const; > >- // CDMInstanceClient >- void updateKeyStatuses(CDMInstanceClient::KeyStatusVector&&) override; >+ // CDMInstanceSessionClient >+ void updateKeyStatuses(CDMInstanceSessionClient::KeyStatusVector&&) override; > > // EventTarget > EventTargetInterface eventTargetInterface() const override { return MediaKeySessionEventTargetInterfaceType; } >@@ -110,13 +110,14 @@ private: > bool m_useDistinctiveIdentifier; > MediaKeySessionType m_sessionType; > Ref<CDM> m_implementation; >- Ref<CDMInstance> m_instance; >+ Ref<CDMInstanceSession> m_instance; > GenericEventQueue m_eventQueue; > GenericTaskQueue<Timer> m_taskQueue; > Vector<Ref<SharedBuffer>> m_recordOfKeyUsage; > double m_firstDecryptTime { 0 }; > double m_latestDecryptTime { 0 }; > Vector<std::pair<Ref<SharedBuffer>, MediaKeyStatus>> m_statuses; >+ WeakPtrFactory<CDMInstanceSessionClient> m_cdmInstanceClientWeakPtrFactory; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp >index 39fbb80e976146cb78a624f71b2ae9f05bab2a2a..152fca424a82196facb596997734b3e09d601716 100644 >--- a/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp >+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp >@@ -64,10 +64,14 @@ ExceptionOr<Ref<MediaKeySession>> MediaKeys::createSession(ScriptExecutionContex > if (!m_implementation->supportsSessions()) > return Exception(InvalidStateError); > >+ auto sessionInstance = m_instance->createSession(); >+ if (!sessionInstance) >+ return Exception(InvalidStateError); >+ > // 3. Let session be a new MediaKeySession object, and initialize it as follows: > // NOTE: Continued in MediaKeySession. > // 4. Return session. >- auto session = MediaKeySession::create(context, makeWeakPtr(*this), sessionType, m_useDistinctiveIdentifier, m_implementation.copyRef(), m_instance.copyRef()); >+ auto session = MediaKeySession::create(context, makeWeakPtr(*this), sessionType, m_useDistinctiveIdentifier, m_implementation.copyRef(), sessionInstance.releaseNonNull()); > m_sessions.append(session.copyRef()); > return WTFMove(session); > } >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 6172a038ba3bf57298dd85037ad201e2226aeb80..7ed0c0d1fb98258e054bd6e4c44cc84eb16fc7d8 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -13311,6 +13311,7 @@ > CD94A5D61F71CB6D00F525C5 /* CDMMessageType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMMessageType.h; sourceTree = "<group>"; }; > CD94A5DA1F71CBB000F525C5 /* CDMClearKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMClearKey.h; sourceTree = "<group>"; }; > CD94A5DB1F71CBB000F525C5 /* CDMClearKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDMClearKey.cpp; sourceTree = "<group>"; }; >+ CD9D375A215163E40049657B /* CDMInstanceSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDMInstanceSession.h; sourceTree = "<group>"; }; > CD9D82731C7AE535006FF066 /* TextureCacheCV.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextureCacheCV.mm; sourceTree = "<group>"; }; > CD9D82741C7AE535006FF066 /* TextureCacheCV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheCV.h; sourceTree = "<group>"; }; > CD9D82771C7B8EE1006FF066 /* VideoTextureCopierCV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoTextureCopierCV.cpp; sourceTree = "<group>"; }; >@@ -24760,6 +24761,7 @@ > CD94A5D11F71CB6B00F525C5 /* CDMFactory.cpp */, > CD94A5D21F71CB6B00F525C5 /* CDMFactory.h */, > CD94A5CE1F71CB6A00F525C5 /* CDMInstance.h */, >+ CD9D375A215163E40049657B /* CDMInstanceSession.h */, > CD94A5D41F71CB6C00F525C5 /* CDMKeyStatus.h */, > CD94A5CD1F71CB6900F525C5 /* CDMKeySystemConfiguration.h */, > CD94A5D31F71CB6C00F525C5 /* CDMMediaCapability.h */, >diff --git a/Source/WebCore/platform/encryptedmedia/CDMInstance.h b/Source/WebCore/platform/encryptedmedia/CDMInstance.h >index e665ccc9b5c3cb6405b49b5c723933522cae3982..4d0d35eab014bb3309f36c185b95fbf2e02a2be1 100644 >--- a/Source/WebCore/platform/encryptedmedia/CDMInstance.h >+++ b/Source/WebCore/platform/encryptedmedia/CDMInstance.h >@@ -36,22 +36,15 @@ > #include <wtf/RefCounted.h> > #include <wtf/TypeCasts.h> > #include <wtf/Vector.h> >+#include <wtf/WeakPtr.h> > > namespace WebCore { > > class SharedBuffer; > >+class CDMInstanceSession; > struct CDMKeySystemConfiguration; > >-class CDMInstanceClient { >-public: >- virtual ~CDMInstanceClient() = default; >- >- using KeyStatus = CDMKeyStatus; >- using KeyStatusVector = Vector<std::pair<Ref<SharedBuffer>, KeyStatus>>; >- virtual void updateKeyStatuses(KeyStatusVector&&) = 0; >-}; >- > class CDMInstance : public RefCounted<CDMInstance> { > public: > virtual ~CDMInstance() = default; >@@ -61,7 +54,6 @@ public: > ClearKey, > FairPlayStreaming, > }; >- > virtual ImplementationType implementationType() const = 0; > > enum SuccessValue { >@@ -69,15 +61,13 @@ public: > Succeeded, > }; > >- using KeyStatus = CDMKeyStatus; >- using LicenseType = CDMSessionType; >- using MessageType = CDMMessageType; >- > virtual SuccessValue initializeWithConfiguration(const CDMKeySystemConfiguration&) = 0; > virtual SuccessValue setDistinctiveIdentifiersAllowed(bool) = 0; > virtual SuccessValue setPersistentStateAllowed(bool) = 0; > virtual SuccessValue setServerCertificate(Ref<SharedBuffer>&&) = 0; > virtual SuccessValue setStorageDirectory(const String&) = 0; >+ virtual const String& keySystem() const = 0; >+ virtual RefPtr<CDMInstanceSession> createSession() = 0; > > enum class HDCPStatus { > Unknown, >@@ -86,38 +76,6 @@ public: > OutputDownscaled, > }; > virtual SuccessValue setHDCPStatus(HDCPStatus) { return Failed; } >- >- virtual void setClient(CDMInstanceClient&) { } >- virtual void clearClient() { } >- >- using LicenseCallback = Function<void(Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, SuccessValue succeeded)>; >- virtual void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) = 0; >- >- using KeyStatusVector = CDMInstanceClient::KeyStatusVector; >- using Message = std::pair<MessageType, Ref<SharedBuffer>>; >- using LicenseUpdateCallback = Function<void(bool sessionWasClosed, std::optional<KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<Message>&& message, SuccessValue succeeded)>; >- virtual void updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback) = 0; >- >- enum class SessionLoadFailure { >- None, >- NoSessionData, >- MismatchedSessionType, >- QuotaExceeded, >- Other, >- }; >- >- using LoadSessionCallback = Function<void(std::optional<KeyStatusVector>&&, std::optional<double>&&, std::optional<Message>&&, SuccessValue, SessionLoadFailure)>; >- virtual void loadSession(LicenseType, const String& sessionId, const String& origin, LoadSessionCallback) = 0; >- >- using CloseSessionCallback = Function<void()>; >- virtual void closeSession(const String& sessionId, CloseSessionCallback) = 0; >- >- using RemoveSessionDataCallback = Function<void(KeyStatusVector&&, std::optional<Ref<SharedBuffer>>&&, SuccessValue)>; >- virtual void removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback) = 0; >- >- virtual void storeRecordOfKeyUsage(const String& sessionId) = 0; >- >- virtual const String& keySystem() const = 0; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h b/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h >new file mode 100644 >index 0000000000000000000000000000000000000000..1017421e921f6d512383d4cf8b7cd3ef242d4985 >--- /dev/null >+++ b/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h >@@ -0,0 +1,101 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#pragma once >+ >+#if ENABLE(ENCRYPTED_MEDIA) >+ >+#include "CDMKeyStatus.h" >+#include "CDMMessageType.h" >+#include "CDMSessionType.h" >+#include <wtf/RefCounted.h> >+#include <wtf/Vector.h> >+#include <wtf/WeakPtr.h> >+ >+namespace WebCore { >+ >+class SharedBuffer; >+ >+class CDMInstanceSessionClient { >+public: >+ virtual ~CDMInstanceSessionClient() = default; >+ >+ using KeyStatus = CDMKeyStatus; >+ using KeyStatusVector = Vector<std::pair<Ref<SharedBuffer>, KeyStatus>>; >+ virtual void updateKeyStatuses(KeyStatusVector&&) = 0; >+}; >+ >+class CDMInstanceSession : public RefCounted<CDMInstanceSession> { >+public: >+ virtual ~CDMInstanceSession() = default; >+ >+ using KeyStatus = CDMKeyStatus; >+ using LicenseType = CDMSessionType; >+ using MessageType = CDMMessageType; >+ >+ virtual void setClient(WeakPtr<CDMInstanceSessionClient>&&) { } >+ virtual void clearClient() { } >+ >+ enum SuccessValue { >+ Failed, >+ Succeeded, >+ }; >+ >+ using LicenseCallback = Function<void(Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, SuccessValue succeeded)>; >+ virtual void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) = 0; >+ >+ using KeyStatusVector = CDMInstanceSessionClient::KeyStatusVector; >+ using Message = std::pair<MessageType, Ref<SharedBuffer>>; >+ using LicenseUpdateCallback = Function<void(bool sessionWasClosed, std::optional<KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<Message>&& message, SuccessValue succeeded)>; >+ virtual void updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback) = 0; >+ >+ enum class SessionLoadFailure { >+ None, >+ NoSessionData, >+ MismatchedSessionType, >+ QuotaExceeded, >+ Other, >+ }; >+ >+ using LoadSessionCallback = Function<void(std::optional<KeyStatusVector>&&, std::optional<double>&&, std::optional<Message>&&, SuccessValue, SessionLoadFailure)>; >+ virtual void loadSession(LicenseType, const String& sessionId, const String& origin, LoadSessionCallback) = 0; >+ >+ using CloseSessionCallback = Function<void()>; >+ virtual void closeSession(const String& sessionId, CloseSessionCallback) = 0; >+ >+ using RemoveSessionDataCallback = Function<void(KeyStatusVector&&, std::optional<Ref<SharedBuffer>>&&, SuccessValue)>; >+ virtual void removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback) = 0; >+ >+ virtual void storeRecordOfKeyUsage(const String& sessionId) = 0; >+}; >+ >+} // namespace WebCore >+ >+#define SPECIALIZE_TYPE_TRAITS_CDM_INSTANCE(ToValueTypeName, ImplementationTypeName) \ >+SPECIALIZE_TYPE_TRAITS_BEGIN(ToValueTypeName) \ >+static bool isType(const WebCore::CDMInstance& instance) { return instance.implementationType() == ImplementationTypeName; } \ >+SPECIALIZE_TYPE_TRAITS_END() >+ >+#endif >diff --git a/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp b/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp >index efad6c16c016e4a1d2e15f548b42518fe84f7a93..4e5a8a91fcf0ff19993bc2628f72ddcdc0326e2b 100644 >--- a/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp >+++ b/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp >@@ -40,7 +40,6 @@ > #include <wtf/NeverDestroyed.h> > #include <wtf/text/Base64.h> > >- > namespace WebCore { > > // ClearKey CENC SystemID. >@@ -50,7 +49,7 @@ const unsigned clearKeyCencSystemIdSize = sizeof(clearKeyCencSystemId); > const unsigned keyIdSize = 16; > > class ClearKeyState { >- using KeyStore = HashMap<String, Vector<CDMInstanceClearKey::Key>>; >+ using KeyStore = HashMap<String, Vector<CDMInstanceSessionClearKey::Key>>; > > public: > static ClearKeyState& singleton(); >@@ -88,7 +87,7 @@ static RefPtr<JSON::Object> parseJSONObject(const SharedBuffer& buffer) > return object; > } > >-static std::optional<Vector<CDMInstanceClearKey::Key>> parseLicenseFormat(const JSON::Object& root) >+static std::optional<Vector<CDMInstanceSessionClearKey::Key>> parseLicenseFormat(const JSON::Object& root) > { > // If the 'keys' key is present in the root object, parse the JSON further > // according to the specified 'license' format. >@@ -101,7 +100,7 @@ static std::optional<Vector<CDMInstanceClearKey::Key>> parseLicenseFormat(const > if (!it->value->asArray(keysArray)) > return std::nullopt; > >- Vector<CDMInstanceClearKey::Key> decodedKeys; >+ Vector<CDMInstanceSessionClearKey::Key> decodedKeys; > bool validFormat = std::all_of(keysArray->begin(), keysArray->end(), > [&decodedKeys] (const auto& value) { > RefPtr<JSON::Object> keyObject; >@@ -120,7 +119,7 @@ static std::optional<Vector<CDMInstanceClearKey::Key>> parseLicenseFormat(const > if (!WTF::base64URLDecode(keyID, { keyIDData }) || !WTF::base64URLDecode(keyValue, { keyValueData })) > return false; > >- decodedKeys.append({ CDMInstanceClearKey::KeyStatus::Usable, SharedBuffer::create(WTFMove(keyIDData)), SharedBuffer::create(WTFMove(keyValueData)) }); >+ decodedKeys.append({ CDMInstanceSessionClearKey::KeyStatus::Usable, SharedBuffer::create(WTFMove(keyIDData)), SharedBuffer::create(WTFMove(keyValueData)) }); > return true; > }); > if (!validFormat) >@@ -493,7 +492,29 @@ CDMInstance::SuccessValue CDMInstanceClearKey::setStorageDirectory(const String& > return storageDirectory.isEmpty() ? Succeeded : Failed; > } > >-void CDMInstanceClearKey::requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback) >+const String& CDMInstanceClearKey::keySystem() const >+{ >+ static const NeverDestroyed<String> s_keySystem = MAKE_STATIC_STRING_IMPL("org.w3.clearkey"); >+ >+ return s_keySystem; >+} >+ >+RefPtr<CDMInstanceSession> CDMInstanceClearKey::createSession() >+{ >+ return adoptRef(new CDMInstanceSessionClearKey()); >+} >+ >+const Vector<CDMInstanceSessionClearKey::Key> CDMInstanceSessionClearKey::keys() const >+{ >+ // Return the keys of all sessions. >+ Vector<CDMInstanceSessionClearKey::Key> allKeys { }; >+ for (auto& key : ClearKeyState::singleton().keys().values()) >+ allKeys.appendVector(key); >+ >+ return allKeys; >+} >+ >+void CDMInstanceSessionClearKey::requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback) > { > static uint32_t s_sessionIdValue = 0; > ++s_sessionIdValue; >@@ -513,17 +534,7 @@ void CDMInstanceClearKey::requestLicense(LicenseType, const AtomicString& initDa > }); > } > >-const Vector<CDMInstanceClearKey::Key> CDMInstanceClearKey::keys() const >-{ >- // Return the keys of all sessions. >- Vector<CDMInstanceClearKey::Key> allKeys { }; >- for (auto& key : ClearKeyState::singleton().keys().values()) >- allKeys.appendVector(key); >- >- return allKeys; >-} >- >-void CDMInstanceClearKey::updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback callback) >+void CDMInstanceSessionClearKey::updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback callback) > { > // Use a helper functor that schedules the callback dispatch, avoiding > // duplicated callOnMainThread() calls. >@@ -624,7 +635,7 @@ void CDMInstanceClearKey::updateLicense(const String& sessionId, LicenseType, co > dispatchCallback(false, std::nullopt, SuccessValue::Failed); > } > >-void CDMInstanceClearKey::loadSession(LicenseType, const String& sessionId, const String&, LoadSessionCallback callback) >+void CDMInstanceSessionClearKey::loadSession(LicenseType, const String& sessionId, const String&, LoadSessionCallback callback) > { > // Use a helper functor that schedules the callback dispatch, avoiding duplicated callOnMainThread() calls. > auto dispatchCallback = >@@ -657,7 +668,7 @@ void CDMInstanceClearKey::loadSession(LicenseType, const String& sessionId, cons > dispatchCallback(WTFMove(keyStatusVector), Succeeded, SessionLoadFailure::None); > } > >-void CDMInstanceClearKey::closeSession(const String&, CloseSessionCallback callback) >+void CDMInstanceSessionClearKey::closeSession(const String&, CloseSessionCallback callback) > { > callOnMainThread( > [weakThis = makeWeakPtr(*this), callback = WTFMove(callback)] { >@@ -668,7 +679,7 @@ void CDMInstanceClearKey::closeSession(const String&, CloseSessionCallback callb > }); > } > >-void CDMInstanceClearKey::removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback callback) >+void CDMInstanceSessionClearKey::removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback callback) > { > // Use a helper functor that schedules the callback dispatch, avoiding duplicated callOnMainThread() calls. > auto dispatchCallback = >@@ -726,15 +737,8 @@ void CDMInstanceClearKey::removeSessionData(const String& sessionId, LicenseType > dispatchCallback(WTFMove(keyStatusVector), Ref<SharedBuffer>(*message), SuccessValue::Succeeded); > } > >-void CDMInstanceClearKey::storeRecordOfKeyUsage(const String&) >-{ >-} >- >-const String& CDMInstanceClearKey::keySystem() const >+void CDMInstanceSessionClearKey::storeRecordOfKeyUsage(const String&) > { >- static const NeverDestroyed<String> s_keySystem = MAKE_STATIC_STRING_IMPL("org.w3.clearkey"); >- >- return s_keySystem; > } > > } // namespace WebCore >diff --git a/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h b/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h >index cd4c8801c19aab0e612352422110af45ea8116f6..12176553b201be1202471a574fa19a16a7cf5661 100644 >--- a/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h >+++ b/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h >@@ -32,6 +32,7 @@ > > #include "CDMFactory.h" > #include "CDMInstance.h" >+#include "CDMInstanceSession.h" > #include "CDMPrivate.h" > #include "SharedBuffer.h" > #include <wtf/WeakPtr.h> >@@ -44,8 +45,8 @@ public: > > virtual ~CDMFactoryClearKey(); > >- std::unique_ptr<CDMPrivate> createCDM(const String&) override; >- bool supportsKeySystem(const String&) override; >+ std::unique_ptr<CDMPrivate> createCDM(const String&) final; >+ bool supportsKeySystem(const String&) final; > > private: > friend class NeverDestroyed<CDMFactoryClearKey>; >@@ -57,21 +58,21 @@ public: > CDMPrivateClearKey(); > virtual ~CDMPrivateClearKey(); > >- bool supportsInitDataType(const AtomicString&) const override; >- bool supportsConfiguration(const CDMKeySystemConfiguration&) const override; >- bool supportsConfigurationWithRestrictions(const CDMKeySystemConfiguration&, const CDMRestrictions&) const override; >- bool supportsSessionTypeWithConfiguration(CDMSessionType&, const CDMKeySystemConfiguration&) const override; >- bool supportsRobustness(const String&) const override; >- CDMRequirement distinctiveIdentifiersRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const override; >- CDMRequirement persistentStateRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const override; >- bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const CDMKeySystemConfiguration&) const override; >- RefPtr<CDMInstance> createInstance() override; >- void loadAndInitialize() override; >- bool supportsServerCertificates() const override; >- bool supportsSessions() const override; >- bool supportsInitData(const AtomicString&, const SharedBuffer&) const override; >- RefPtr<SharedBuffer> sanitizeResponse(const SharedBuffer&) const override; >- std::optional<String> sanitizeSessionId(const String&) const override; >+ bool supportsInitDataType(const AtomicString&) const final; >+ bool supportsConfiguration(const CDMKeySystemConfiguration&) const final; >+ bool supportsConfigurationWithRestrictions(const CDMKeySystemConfiguration&, const CDMRestrictions&) const final; >+ bool supportsSessionTypeWithConfiguration(CDMSessionType&, const CDMKeySystemConfiguration&) const final; >+ bool supportsRobustness(const String&) const final; >+ CDMRequirement distinctiveIdentifiersRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const final; >+ CDMRequirement persistentStateRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const final; >+ bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const CDMKeySystemConfiguration&) const final; >+ RefPtr<CDMInstance> createInstance() final; >+ void loadAndInitialize() final; >+ bool supportsServerCertificates() const final; >+ bool supportsSessions() const final; >+ bool supportsInitData(const AtomicString&, const SharedBuffer&) const final; >+ RefPtr<SharedBuffer> sanitizeResponse(const SharedBuffer&) const final; >+ std::optional<String> sanitizeSessionId(const String&) const final; > }; > > class CDMInstanceClearKey final : public CDMInstance, public CanMakeWeakPtr<CDMInstanceClearKey> { >@@ -81,20 +82,13 @@ public: > > ImplementationType implementationType() const final { return ImplementationType::ClearKey; } > >- SuccessValue initializeWithConfiguration(const CDMKeySystemConfiguration&) override; >- SuccessValue setDistinctiveIdentifiersAllowed(bool) override; >- SuccessValue setPersistentStateAllowed(bool) override; >- SuccessValue setServerCertificate(Ref<SharedBuffer>&&) override; >- SuccessValue setStorageDirectory(const String&) override; >- >- void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) override; >- void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) override; >- void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) override; >- void closeSession(const String&, CloseSessionCallback) override; >- void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) override; >- void storeRecordOfKeyUsage(const String&) override; >- >+ SuccessValue initializeWithConfiguration(const CDMKeySystemConfiguration&) final; >+ SuccessValue setDistinctiveIdentifiersAllowed(bool) final; >+ SuccessValue setPersistentStateAllowed(bool) final; >+ SuccessValue setServerCertificate(Ref<SharedBuffer>&&) final; >+ SuccessValue setStorageDirectory(const String&) final; > const String& keySystem() const final; >+ RefPtr<CDMInstanceSession> createSession() final; > > struct Key { > KeyStatus status; >@@ -105,6 +99,16 @@ public: > const Vector<Key> keys() const; > }; > >+class CDMInstanceSessionClearKey final : public CDMInstanceSession, public CanMakeWeakPtr<CDMInstanceSessionClearKey> { >+public: >+ void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) final; >+ void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) final; >+ void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) final; >+ void closeSession(const String&, CloseSessionCallback) final; >+ void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) final; >+ void storeRecordOfKeyUsage(const String&) final; >+}; >+ > } // namespace WebCore > > SPECIALIZE_TYPE_TRAITS_CDM_INSTANCE(WebCore::CDMInstanceClearKey, WebCore::CDMInstance::ImplementationType::ClearKey); >diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h b/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h >index 83b9d5023cc18a9e4293ff625af1533ca2fa010f..2d77023bfa0d6378e20a1ac583282fab478c8d46 100644 >--- a/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h >+++ b/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h >@@ -28,9 +28,10 @@ > #if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION) > > #include "CDMInstance.h" >+#include "CDMInstanceSession.h" > #include <wtf/Function.h> >+#include <wtf/HashMap.h> > #include <wtf/RetainPtr.h> >-#include <wtf/WeakPtr.h> > #include <wtf/text/WTFString.h> > > OBJC_CLASS AVContentKeyRequest; >@@ -42,6 +43,8 @@ OBJC_CLASS WebCoreFPSContentKeySessionDelegate; > > namespace WebCore { > >+class CDMInstanceSessionFairPlayStreamingAVFObjC; >+ > class CDMInstanceFairPlayStreamingAVFObjC final : public CDMInstance, public CanMakeWeakPtr<CDMInstanceFairPlayStreamingAVFObjC> { > public: > CDMInstanceFairPlayStreamingAVFObjC(); >@@ -58,15 +61,9 @@ public: > SuccessValue setPersistentStateAllowed(bool) final; > SuccessValue setServerCertificate(Ref<SharedBuffer>&&) final; > SuccessValue setStorageDirectory(const String&) final; >+ RefPtr<CDMInstanceSession> createSession() final; > >- void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) final; >- void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) final; >- void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) final; >- void closeSession(const String&, CloseSessionCallback) final; >- void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) final; >- void storeRecordOfKeyUsage(const String&) final; >- void setClient(CDMInstanceClient&) final; >- void clearClient() final; >+ void processContentKeyRequestForSession(CDMInstanceSessionFairPlayStreamingAVFObjC&, RetainPtr<NSString>&& identifier, RetainPtr<NSData>&& initData); > > const String& keySystem() const final; > >@@ -79,21 +76,62 @@ public: > void sessionIdentifierChanged(NSData *); > void outputObscuredDueToInsufficientExternalProtectionChanged(bool); > >+ NSURL *storageDirectory() const { return m_storageDirectory.get(); } > AVContentKeySession *contentKeySession() { return m_session.get(); } >+ bool persistentStateAllowed() const { return m_persistentStateAllowed; } >+ SharedBuffer* serverCertificate() const { return m_serverCertificate.get(); } > > private: >- bool isLicenseTypeSupported(LicenseType) const; >+ void processNextContentKeyRequest(); > >- Vector<Ref<SharedBuffer>> keyIDs(); >+ struct ContentKeyRequest { >+ WeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC> sessionInstance; >+ RetainPtr<NSString> identifier; >+ RetainPtr<NSData> initData; >+ }; >+ Vector<ContentKeyRequest> m_currentRequests; >+ >+ HashMap<RetainPtr<AVContentKeyRequest>, WeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC>> m_requestMap; > > RefPtr<SharedBuffer> m_serverCertificate; > bool m_persistentStateAllowed { true }; > RetainPtr<NSURL> m_storageDirectory; > RetainPtr<AVContentKeySession> m_session; >- RetainPtr<AVContentKeyRequest> m_request; > RetainPtr<WebCoreFPSContentKeySessionDelegate> m_delegate; >+}; >+ >+class CDMInstanceSessionFairPlayStreamingAVFObjC final : public CDMInstanceSession, public CanMakeWeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC> { >+public: >+ CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&&); >+ >+ // CDMInstanceSession >+ void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) final; >+ void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) final; >+ void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) final; >+ void closeSession(const String&, CloseSessionCallback) final; >+ void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) final; >+ void storeRecordOfKeyUsage(const String&) final; >+ void setClient(WeakPtr<CDMInstanceSessionClient>&&) final; >+ void clearClient() final; >+ >+ void didProvideRequest(AVContentKeyRequest *); >+ void didProvideRenewingRequest(AVContentKeyRequest *); >+ void didProvidePersistableRequest(AVContentKeyRequest *); >+ void didFailToProvideRequest(AVContentKeyRequest *, NSError *); >+ void requestDidSucceed(AVContentKeyRequest *); >+ bool shouldRetryRequestForReason(AVContentKeyRequest *, NSString *); >+ void sessionIdentifierChanged(NSData *); >+ void outputObscuredDueToInsufficientExternalProtectionChanged(bool); >+ >+ Vector<Ref<SharedBuffer>> keyIDs(); >+ >+private: >+ bool isLicenseTypeSupported(LicenseType) const; >+ >+ Ref<CDMInstanceFairPlayStreamingAVFObjC> m_instance; >+ RetainPtr<AVContentKeyRequest> m_request; > Vector<RetainPtr<NSData>> m_expiredSessions; >- CDMInstanceClient* m_client; >+ WeakPtr<CDMInstanceSessionClient> m_client; > String m_sessionId; > > LicenseCallback m_requestLicenseCallback; >@@ -101,6 +139,7 @@ private: > CloseSessionCallback m_closeSessionCallback; > RemoveSessionDataCallback m_removeSessionDataCallback; > }; >+ > } > > SPECIALIZE_TYPE_TRAITS_CDM_INSTANCE(WebCore::CDMInstanceFairPlayStreamingAVFObjC, WebCore::CDMInstance::ImplementationType::FairPlayStreaming) >diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm b/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm >index df3bc09802ac6be35c01d6239ebf85d0f5a409aa..1addcb052db12c428dfa325885e8c0781ca49915 100644 >--- a/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm >+++ b/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm >@@ -221,19 +221,122 @@ CDMInstance::SuccessValue CDMInstanceFairPlayStreamingAVFObjC::setStorageDirecto > return Succeeded; > } > >-bool CDMInstanceFairPlayStreamingAVFObjC::isLicenseTypeSupported(LicenseType licenseType) const >+RefPtr<CDMInstanceSession> CDMInstanceFairPlayStreamingAVFObjC::createSession() > { >- switch (licenseType) { >- case CDMSessionType::PersistentLicense: >- return m_persistentStateAllowed && supportsPersistentKeys(); >- case CDMSessionType::PersistentUsageRecord: >- return m_persistentStateAllowed && supportsPersistableState(); >- case CDMSessionType::Temporary: >- return true; >+ return adoptRef(new CDMInstanceSessionFairPlayStreamingAVFObjC(*this)); >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::processContentKeyRequestForSession(CDMInstanceSessionFairPlayStreamingAVFObjC& session, RetainPtr<NSString>&& identifier, RetainPtr<NSData>&& initData) >+{ >+ m_currentRequests.append({ makeWeakPtr(session), WTFMove(identifier), WTFMove(initData) }); >+ if (m_currentRequests.size() == 1) >+ processNextContentKeyRequest(); >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::processNextContentKeyRequest() >+{ >+ if (m_currentRequests.isEmpty()) >+ return; >+ >+ auto& nextRequest = m_currentRequests.first(); >+ [m_session processContentKeyRequestWithIdentifier:nextRequest.identifier.get() initializationData:nextRequest.initData.get() options:nil]; >+} >+ >+const String& CDMInstanceFairPlayStreamingAVFObjC::keySystem() const >+{ >+ static NeverDestroyed<String> s_keySystem { "com.apple.fps"_s }; >+ return s_keySystem; >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request) >+{ >+ if (m_currentRequests.isEmpty()) >+ return; >+ >+ auto currentRequest = WTFMove(m_currentRequests.first()); >+ m_currentRequests.remove(0); >+ >+ if (!currentRequest.sessionInstance) >+ return; >+ >+ m_requestMap.set(request, currentRequest.sessionInstance); >+ currentRequest.sessionInstance->didProvideRequest(request); >+ processNextContentKeyRequest(); >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request) >+{ >+ if (m_currentRequests.isEmpty()) >+ return; >+ >+ auto currentRequest = WTFMove(m_currentRequests.first()); >+ m_currentRequests.remove(0); >+ >+ if (!currentRequest.sessionInstance) >+ return; >+ >+ m_requestMap.set(request, currentRequest.sessionInstance); >+ currentRequest.sessionInstance->didProvideRenewingRequest(request); >+ processNextContentKeyRequest(); >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request) >+{ >+ if (m_currentRequests.isEmpty()) >+ return; >+ >+ auto currentRequest = WTFMove(m_currentRequests.first()); >+ m_currentRequests.remove(0); >+ >+ if (!currentRequest.sessionInstance) >+ return; >+ >+ m_requestMap.set(request, currentRequest.sessionInstance); >+ currentRequest.sessionInstance->didProvidePersistableRequest(request); >+ processNextContentKeyRequest(); >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error) >+{ >+ if (auto sessionInterface = m_requestMap.get(request)) >+ sessionInterface->didFailToProvideRequest(request, error); >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request) >+{ >+ if (auto sessionInterface = m_requestMap.get(request)) >+ sessionInterface->requestDidSucceed(request); >+} >+ >+bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason) >+{ >+ if (auto sessionInterface = m_requestMap.get(request)) >+ return sessionInterface->shouldRetryRequestForReason(request, reason); >+ return false; >+} >+ >+void CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessionIdentifier) >+{ >+ for (auto sessionInterface : m_requestMap.values()) { >+ if (sessionInterface) >+ sessionInterface->sessionIdentifierChanged(sessionIdentifier); > } > } > >-Vector<Ref<SharedBuffer>> CDMInstanceFairPlayStreamingAVFObjC::keyIDs() >+void CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured) >+{ >+ for (auto sessionInterface : m_requestMap.values()) { >+ if (sessionInterface) >+ sessionInterface->outputObscuredDueToInsufficientExternalProtectionChanged(obscured); >+ } >+} >+ >+CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&& instance) >+ : m_instance(WTFMove(instance)) >+{ >+} >+ >+Vector<Ref<SharedBuffer>> CDMInstanceSessionFairPlayStreamingAVFObjC::keyIDs() > { > // FIXME(rdar://problem/35597141): use the future AVContentKeyRequest keyID property, rather than parsing it out of the init > // data, to get the keyID. >@@ -250,14 +353,14 @@ Vector<Ref<SharedBuffer>> CDMInstanceFairPlayStreamingAVFObjC::keyIDs() > return { }; > } > >-void CDMInstanceFairPlayStreamingAVFObjC::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback) > { > if (!isLicenseTypeSupported(licenseType)) { > callback(SharedBuffer::create(), emptyString(), false, Failed); > return; > } > >- if (!m_serverCertificate) { >+ if (!m_instance->serverCertificate()) { > callback(SharedBuffer::create(), emptyString(), false, Failed); > return; > } >@@ -275,7 +378,7 @@ void CDMInstanceFairPlayStreamingAVFObjC::requestLicense(LicenseType licenseType > } > > m_requestLicenseCallback = WTFMove(callback); >- [m_session processContentKeyRequestWithIdentifier:identifier.get() initializationData:initializationData.get() options:nil]; >+ m_instance->processContentKeyRequestForSession(*this, WTFMove(identifier), WTFMove(initializationData)); > } > > static bool isEqual(const SharedBuffer& data, const String& value) >@@ -296,14 +399,23 @@ static bool isEqual(const SharedBuffer& data, const String& value) > return stringOrException.returnValue() == value; > } > >-void CDMInstanceFairPlayStreamingAVFObjC::updateLicense(const String&, LicenseType, const SharedBuffer& responseData, LicenseUpdateCallback callback) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense(const String&, LicenseType, const SharedBuffer& responseData, LicenseUpdateCallback callback) > { > if (!m_expiredSessions.isEmpty() && isEqual(responseData, "acknowledged"_s)) { > auto expiredSessions = adoptNS([[NSMutableArray alloc] init]); > for (auto& session : m_expiredSessions) >- [expiredSessions addObject:session.get()]; >- RetainPtr<NSData> appIdentifier = m_serverCertificate->createNSData(); >- [getAVContentKeySessionClass() removePendingExpiredSessionReports:expiredSessions.get() withAppIdentifier:appIdentifier.get() storageDirectoryAtURL:m_storageDirectory.get()]; >+ [expiredSessions addObject:session.get()]; >+ >+ auto* certificate = m_instance->serverCertificate(); >+ auto* storageDirectory = m_instance->storageDirectory(); >+ >+ if (!certificate || !storageDirectory) { >+ callback(false, std::nullopt, std::nullopt, std::nullopt, Failed); >+ return; >+ } >+ >+ RetainPtr<NSData> appIdentifier = certificate->createNSData(); >+ [getAVContentKeySessionClass() removePendingExpiredSessionReports:expiredSessions.get() withAppIdentifier:appIdentifier.get() storageDirectoryAtURL:storageDirectory]; > callback(false, { }, std::nullopt, std::nullopt, Succeeded); > return; > } >@@ -333,22 +445,24 @@ void CDMInstanceFairPlayStreamingAVFObjC::updateLicense(const String&, LicenseTy > m_updateLicenseCallback = WTFMove(callback); > } > >-void CDMInstanceFairPlayStreamingAVFObjC::loadSession(LicenseType licenseType, const String& sessionId, const String& origin, LoadSessionCallback callback) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::loadSession(LicenseType licenseType, const String& sessionId, const String& origin, LoadSessionCallback callback) > { > UNUSED_PARAM(origin); > if (licenseType == LicenseType::PersistentUsageRecord) { >- if (!m_persistentStateAllowed || !m_storageDirectory) { >+ auto* storageDirectory = m_instance->storageDirectory(); >+ if (!m_instance->persistentStateAllowed() || storageDirectory) { > callback(std::nullopt, std::nullopt, std::nullopt, Failed, SessionLoadFailure::MismatchedSessionType); > return; > } >- if (!m_serverCertificate) { >- callback(std::nullopt, std::nullopt, std::nullopt, Failed, SessionLoadFailure::Other); >+ auto* certificate = m_instance->serverCertificate(); >+ if (!certificate) { >+ callback(std::nullopt, std::nullopt, std::nullopt, Failed, SessionLoadFailure::NoSessionData); > return; > } > >- RetainPtr<NSData> appIdentifier = m_serverCertificate->createNSData(); >+ RetainPtr<NSData> appIdentifier = certificate->createNSData(); > KeyStatusVector changedKeys; >- for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:m_storageDirectory.get()]) { >+ for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:storageDirectory]) { > NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr]; > NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey]; > if (![playbackSessionIdValue isKindOfClass:[NSString class]]) >@@ -370,7 +484,7 @@ void CDMInstanceFairPlayStreamingAVFObjC::loadSession(LicenseType licenseType, c > } > } > >-void CDMInstanceFairPlayStreamingAVFObjC::closeSession(const String&, CloseSessionCallback callback) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession(const String&, CloseSessionCallback callback) > { > if (m_requestLicenseCallback) { > m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed); >@@ -384,25 +498,28 @@ void CDMInstanceFairPlayStreamingAVFObjC::closeSession(const String&, CloseSessi > m_removeSessionDataCallback({ }, std::nullopt, Failed); > m_removeSessionDataCallback = nullptr; > } >- m_session = nullptr; > m_request = nullptr; > callback(); > } > >-void CDMInstanceFairPlayStreamingAVFObjC::removeSessionData(const String& sessionId, LicenseType licenseType, RemoveSessionDataCallback callback) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData(const String& sessionId, LicenseType licenseType, RemoveSessionDataCallback callback) > { >- [m_session expire]; >+ // FIXME: We should be able to expire individual AVContentKeyRequests rather than the entire AVContentKeySession. >+ [m_instance->contentKeySession() expire]; > > if (licenseType == LicenseType::PersistentUsageRecord) { >- if (!m_persistentStateAllowed || !m_storageDirectory || !m_serverCertificate) { >+ auto* storageDirectory = m_instance->storageDirectory(); >+ auto* certificate = m_instance->serverCertificate(); >+ >+ if (!m_instance->persistentStateAllowed() || !storageDirectory || !certificate) { > callback({ }, std::nullopt, Failed); > return; > } > >- RetainPtr<NSData> appIdentifier = m_serverCertificate->createNSData(); >+ RetainPtr<NSData> appIdentifier = certificate->createNSData(); > RetainPtr<NSMutableArray> expiredSessionsArray = adoptNS([[NSMutableArray alloc] init]); > KeyStatusVector changedKeys; >- for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:m_storageDirectory.get()]) { >+ for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:storageDirectory]) { > NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr]; > NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey]; > if (![playbackSessionIdValue isKindOfClass:[NSString class]]) >@@ -422,34 +539,30 @@ void CDMInstanceFairPlayStreamingAVFObjC::removeSessionData(const String& sessio > } > } > >-void CDMInstanceFairPlayStreamingAVFObjC::storeRecordOfKeyUsage(const String&) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::storeRecordOfKeyUsage(const String&) > { > // no-op; key usage data is stored automatically. > } > >-void CDMInstanceFairPlayStreamingAVFObjC::setClient(CDMInstanceClient& client) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::setClient(WeakPtr<CDMInstanceSessionClient>&& client) > { >- m_client = &client; >+ m_client = WTFMove(client); > } > >-void CDMInstanceFairPlayStreamingAVFObjC::clearClient() >+void CDMInstanceSessionFairPlayStreamingAVFObjC::clearClient() > { > m_client = nullptr; > } > >-const String& CDMInstanceFairPlayStreamingAVFObjC::keySystem() const >-{ >- static NeverDestroyed<String> s_keySystem { "com.apple.fps"_s }; >- return s_keySystem; >-} >- >-void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request) > { > m_request = request; > if (!m_requestLicenseCallback) > return; > >- RetainPtr<NSData> appIdentifier = m_serverCertificate ? m_serverCertificate->createNSData() : nullptr; >+ RetainPtr<NSData> appIdentifier; >+ if (auto* certificate = m_instance->serverCertificate()) >+ appIdentifier = certificate->createNSData(); > Vector<Ref<SharedBuffer>> keyIDs = this->keyIDs(); > > if (keyIDs.isEmpty()) { >@@ -473,17 +586,17 @@ void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest > }]; > } > >-void CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request) > { > UNUSED_PARAM(request); > } > >-void CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request) > { > UNUSED_PARAM(request); > } > >-void CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error) > { > UNUSED_PARAM(request); > UNUSED_PARAM(error); >@@ -491,7 +604,7 @@ void CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRe > m_updateLicenseCallback(false, std::nullopt, std::nullopt, std::nullopt, Failed); > } > >-void CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request) > { > UNUSED_PARAM(request); > if (!m_updateLicenseCallback) >@@ -504,7 +617,7 @@ void CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest > m_updateLicenseCallback(false, std::make_optional(WTFMove(keyStatuses)), std::nullopt, std::nullopt, Succeeded); > } > >-bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason) >+bool CDMInstanceSessionFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason) > { > UNUSED_PARAM(request); > UNUSED_PARAM(reason); >@@ -512,7 +625,7 @@ bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentK > return false; > } > >-void CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessionIdentifier) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessionIdentifier) > { > if (!sessionIdentifier) { > m_sessionId = emptyString(); >@@ -523,7 +636,7 @@ void CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessi > m_sessionId = sessionIdentifierString.get(); > } > >-void CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured) >+void CDMInstanceSessionFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured) > { > if (!m_client || !m_request) > return; >@@ -556,6 +669,18 @@ void CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExterna > m_client->updateKeyStatuses(WTFMove(keyStatuses)); > } > >+bool CDMInstanceSessionFairPlayStreamingAVFObjC::isLicenseTypeSupported(LicenseType licenseType) const >+{ >+ switch (licenseType) { >+ case CDMSessionType::PersistentLicense: >+ return m_instance->persistentStateAllowed() && m_instance->supportsPersistentKeys(); >+ case CDMSessionType::PersistentUsageRecord: >+ return m_instance->persistentStateAllowed() && m_instance->supportsPersistableState(); >+ case CDMSessionType::Temporary: >+ return true; >+ } >+} >+ > } > > #endif // ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION) >diff --git a/Source/WebCore/testing/MockCDMFactory.cpp b/Source/WebCore/testing/MockCDMFactory.cpp >index 12bc7f602f1e3e5377186c3ec35a9bf42c940d8e..c2026463c14fd64c25d3738b0b552118cc2e7187 100644 >--- a/Source/WebCore/testing/MockCDMFactory.cpp >+++ b/Source/WebCore/testing/MockCDMFactory.cpp >@@ -269,9 +269,26 @@ CDMInstance::SuccessValue MockCDMInstance::setStorageDirectory(const String&) > return Succeeded; > } > >-void MockCDMInstance::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback) >+const String& MockCDMInstance::keySystem() const > { >- MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr; >+ static const NeverDestroyed<String> s_keySystem = MAKE_STATIC_STRING_IMPL("org.webkit.mock"); >+ >+ return s_keySystem; >+} >+ >+RefPtr<CDMInstanceSession> MockCDMInstance::createSession() >+{ >+ return adoptRef(new MockCDMInstanceSession(makeWeakPtr(*this))); >+} >+ >+MockCDMInstanceSession::MockCDMInstanceSession(WeakPtr<MockCDMInstance>&& instance) >+ : m_instance(WTFMove(instance)) >+{ >+} >+ >+void MockCDMInstanceSession::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback) >+{ >+ MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr; > if (!factory) { > callback(SharedBuffer::create(), emptyAtom(), false, SuccessValue::Failed); > return; >@@ -295,9 +312,9 @@ void MockCDMInstance::requestLicense(LicenseType licenseType, const AtomicString > callback(SharedBuffer::create(license.data(), license.length()), sessionID, false, SuccessValue::Succeeded); > } > >-void MockCDMInstance::updateLicense(const String& sessionID, LicenseType, const SharedBuffer& response, LicenseUpdateCallback callback) >+void MockCDMInstanceSession::updateLicense(const String& sessionID, LicenseType, const SharedBuffer& response, LicenseUpdateCallback callback) > { >- MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr; >+ MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr; > if (!factory) { > callback(false, std::nullopt, std::nullopt, std::nullopt, SuccessValue::Failed); > return; >@@ -329,9 +346,9 @@ void MockCDMInstance::updateLicense(const String& sessionID, LicenseType, const > callback(false, WTFMove(changedKeys), std::nullopt, std::nullopt, SuccessValue::Succeeded); > } > >-void MockCDMInstance::loadSession(LicenseType, const String&, const String&, LoadSessionCallback callback) >+void MockCDMInstanceSession::loadSession(LicenseType, const String&, const String&, LoadSessionCallback callback) > { >- MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr; >+ MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr; > if (!factory) { > callback(std::nullopt, std::nullopt, std::nullopt, SuccessValue::Failed, SessionLoadFailure::Other); > return; >@@ -345,9 +362,9 @@ void MockCDMInstance::loadSession(LicenseType, const String&, const String&, Loa > callback(std::nullopt, std::nullopt, WTFMove(message), SuccessValue::Succeeded, SessionLoadFailure::None); > } > >-void MockCDMInstance::closeSession(const String& sessionID, CloseSessionCallback callback) >+void MockCDMInstanceSession::closeSession(const String& sessionID, CloseSessionCallback callback) > { >- MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr; >+ MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr; > if (!factory) { > callback(); > return; >@@ -357,9 +374,9 @@ void MockCDMInstance::closeSession(const String& sessionID, CloseSessionCallback > callback(); > } > >-void MockCDMInstance::removeSessionData(const String& id, LicenseType, RemoveSessionDataCallback callback) >+void MockCDMInstanceSession::removeSessionData(const String& id, LicenseType, RemoveSessionDataCallback callback) > { >- MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr; >+ MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr; > if (!factory) { > callback({ }, std::nullopt, SuccessValue::Failed); > return; >@@ -375,18 +392,11 @@ void MockCDMInstance::removeSessionData(const String& id, LicenseType, RemoveSes > callback(WTFMove(keyStatusVector), SharedBuffer::create(message.data(), message.length()), SuccessValue::Succeeded); > } > >-void MockCDMInstance::storeRecordOfKeyUsage(const String&) >+void MockCDMInstanceSession::storeRecordOfKeyUsage(const String&) > { > // FIXME: This should be implemented along with the support for persistent-usage-record sessions. > } > >-const String& MockCDMInstance::keySystem() const >-{ >- static const NeverDestroyed<String> s_keySystem = MAKE_STATIC_STRING_IMPL("org.webkit.mock"); >- >- return s_keySystem; >-} >- > } > > #endif >diff --git a/Source/WebCore/testing/MockCDMFactory.h b/Source/WebCore/testing/MockCDMFactory.h >index 216d29a0a7c3376d833899d1540027b283ae83f4..84d3a6c830a703e6afbe121870af7ac71a2cf420 100644 >--- a/Source/WebCore/testing/MockCDMFactory.h >+++ b/Source/WebCore/testing/MockCDMFactory.h >@@ -30,6 +30,7 @@ > #include "CDM.h" > #include "CDMFactory.h" > #include "CDMInstance.h" >+#include "CDMInstanceSession.h" > #include "CDMPrivate.h" > #include "MediaKeysRequirement.h" > #include <wtf/HashMap.h> >@@ -121,10 +122,14 @@ private: > WeakPtr<MockCDMFactory> m_factory; > }; > >-class MockCDMInstance : public CDMInstance { >+class MockCDMInstance : public CDMInstance, public CanMakeWeakPtr<MockCDMInstance> { > public: > MockCDMInstance(WeakPtr<MockCDM>); > >+ MockCDMFactory* factory() const { return m_cdm ? m_cdm->factory() : nullptr; } >+ bool distinctiveIdentifiersAllowed() const { return m_distinctiveIdentifiersAllowed; } >+ bool persistentStateAllowed() const { return m_persistentStateAllowed; } >+ > private: > ImplementationType implementationType() const final { return ImplementationType::Mock; } > SuccessValue initializeWithConfiguration(const MediaKeySystemConfiguration&) final; >@@ -132,6 +137,19 @@ private: > SuccessValue setPersistentStateAllowed(bool) final; > SuccessValue setServerCertificate(Ref<SharedBuffer>&&) final; > SuccessValue setStorageDirectory(const String&) final; >+ const String& keySystem() const final; >+ RefPtr<CDMInstanceSession> createSession() final; >+ >+ WeakPtr<MockCDM> m_cdm; >+ bool m_distinctiveIdentifiersAllowed { true }; >+ bool m_persistentStateAllowed { true }; >+}; >+ >+class MockCDMInstanceSession : public CDMInstanceSession { >+public: >+ MockCDMInstanceSession(WeakPtr<MockCDMInstance>&&); >+ >+private: > void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) final; > void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) final; > void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) final; >@@ -139,11 +157,7 @@ private: > void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) final; > void storeRecordOfKeyUsage(const String&) final; > >- const String& keySystem() const final; >- >- WeakPtr<MockCDM> m_cdm; >- bool m_distinctiveIdentifiersAllowed { true }; >- bool m_persistentStateAllowed { true }; >+ WeakPtr<MockCDMInstance> m_instance; > }; > > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 189725
:
350076
|
350127
|
350222