Modified: trunk/Source/WebCore/ChangeLog (173790 => 173791)
--- trunk/Source/WebCore/ChangeLog 2014-09-20 06:02:25 UTC (rev 173790)
+++ trunk/Source/WebCore/ChangeLog 2014-09-20 06:49:19 UTC (rev 173791)
@@ -1,5 +1,28 @@
2014-09-19 Jer Noble <[email protected]>
+ [EME][Mac] Support secure proof of key release in the com.apple.fps.2_0 keysystem.
+ https://bugs.webkit.org/show_bug.cgi?id=136898
+
+ Reviewed by Eric Carlson.
+
+ Add support for proof of key release to the CDM by supporting a new "mime" type called
+ "keyrelease". When a session of type "keyrelease" is created, the initData is the server
+ certificate, the keyMessage contains the first stored proof of key release if present,
+ and closing the session will remove that proof from storage.
+
+ * platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm:
+ (WebCore::CDMPrivateMediaSourceAVFObjC::supportsKeySystemAndMimeType):
+ * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h:
+ * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm:
+ (WebCore::CDMSessionMediaSourceAVFObjC::CDMSessionMediaSourceAVFObjC):
+ (WebCore::CDMSessionMediaSourceAVFObjC::generateKeyRequest):
+ (WebCore::CDMSessionMediaSourceAVFObjC::releaseKeys):
+ (WebCore::sessionStorageDirectory):
+ (WebCore::CDMSessionMediaSourceAVFObjC::update):
+ (WebCore::CDMSessionMediaSourceAVFObjC::generateKeyReleaseMessage):
+
+2014-09-19 Jer Noble <[email protected]>
+
[Media][Mac] Buffered range slides around as you resize a window
https://bugs.webkit.org/show_bug.cgi?id=136960
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm (173790 => 173791)
--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm 2014-09-20 06:02:25 UTC (rev 173790)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm 2014-09-20 06:49:19 UTC (rev 173791)
@@ -54,6 +54,9 @@
return false;
if (!mimeType.isEmpty()) {
+ if (equalIgnoringCase(mimeType, "keyrelease"))
+ return true;
+
MediaEngineSupportParameters parameters;
parameters.isMediaSource = true;
parameters.type = mimeType;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h (173790 => 173791)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h 2014-09-20 06:02:25 UTC (rev 173790)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h 2014-09-20 06:49:19 UTC (rev 173791)
@@ -56,12 +56,16 @@
void removeSourceBuffer(SourceBufferPrivateAVFObjC*);
protected:
+ PassRefPtr<Uint8Array> generateKeyReleaseMessage(unsigned short& errorCode, unsigned long& systemCode);
+
Vector<RefPtr<SourceBufferPrivateAVFObjC>> m_sourceBuffers;
CDMSessionClient* m_client;
RetainPtr<AVStreamSession> m_streamSession;
RefPtr<Uint8Array> m_initData;
RefPtr<Uint8Array> m_certificate;
+ RetainPtr<NSData> m_expiredSession;
String m_sessionId;
+ enum { Normal, KeyRelease } m_mode;
};
inline CDMSessionMediaSourceAVFObjC* toCDMSessionMediaSourceAVFObjC(CDMSession* session)
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm (173790 => 173791)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm 2014-09-20 06:02:25 UTC (rev 173790)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm 2014-09-20 06:49:19 UTC (rev 173791)
@@ -52,7 +52,7 @@
@end
@interface AVStreamSession : NSObject
-- (instancetype)initWithAppIdentifier:(NSData *)appIdentifier;
+- (instancetype)initWithAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL;
- (void)addStreamDataParser:(AVStreamDataParser *)streamDataParser;
- (void)removeStreamDataParser:(AVStreamDataParser *)streamDataParser;
- (void)expire;
@@ -65,6 +65,7 @@
CDMSessionMediaSourceAVFObjC::CDMSessionMediaSourceAVFObjC()
: m_client(nullptr)
, m_sessionId(createCanonicalUUIDString())
+ , m_mode(Normal)
{
}
@@ -90,6 +91,11 @@
m_initData = initData;
+ if (equalIgnoringCase(mimeType, "keyrelease")) {
+ m_mode = KeyRelease;
+ return generateKeyReleaseMessage(errorCode, systemCode);
+ }
+
String certificateString(ASCIILiteral("certificate"));
RefPtr<Uint8Array> array = Uint8Array::create(certificateString.length());
for (unsigned i = 0, length = certificateString.length(); i < length; ++i)
@@ -99,6 +105,12 @@
void CDMSessionMediaSourceAVFObjC::releaseKeys()
{
+ if (m_mode == KeyRelease) {
+ RetainPtr<NSData> certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate->data() length:m_certificate->length()]);
+ [getAVStreamSessionClass() removePendingExpiredSessionReports:@[m_expiredSession.get()] withAppIdentifier:certificateData.get()];
+ return;
+ }
+
if (m_streamSession) {
LOG(Media, "CDMSessionMediaSourceAVFObjC::releaseKeys(%p) - expiring stream session", this);
[m_streamSession expire];
@@ -121,8 +133,27 @@
return !literal[length];
}
+static const String& sessionStorageDirectory()
+{
+ static NeverDestroyed<String> sessionDirectoryPath;
+
+ if (sessionDirectoryPath.get().isEmpty()) {
+ char cacheDirectoryPath[PATH_MAX];
+ if (!confstr(_CS_DARWIN_USER_CACHE_DIR, cacheDirectoryPath, PATH_MAX))
+ return WTF::emptyString();
+
+ sessionDirectoryPath.get().append(String(cacheDirectoryPath, strlen(cacheDirectoryPath)));
+ sessionDirectoryPath.get().append(ASCIILiteral("AVStreamSession/"));
+ }
+
+ return sessionDirectoryPath.get();
+}
+
bool CDMSessionMediaSourceAVFObjC::update(Uint8Array* key, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, unsigned long& systemCode)
{
+ if (m_mode == KeyRelease)
+ return false;
+
bool shouldGenerateKeyRequest = !m_certificate || isEqual(key, "renew");
if (!m_certificate) {
LOG(Media, "CDMSessionMediaSourceAVFObjC::update(%p) - certificate data", this);
@@ -141,7 +172,7 @@
if (shouldGenerateKeyRequest) {
RetainPtr<NSData> certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate->data() length:m_certificate->length()]);
if (getAVStreamSessionClass()) {
- m_streamSession = adoptNS([[getAVStreamSessionClass() alloc] initWithAppIdentifier:certificateData.get()]);
+ m_streamSession = adoptNS([[getAVStreamSessionClass() alloc] initWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:sessionStorageDirectory()]]);
for (auto& sourceBuffer : m_sourceBuffers)
[m_streamSession addStreamDataParser:sourceBuffer->parser()];
LOG(Media, "CDMSessionMediaSourceAVFObjC::update(%p) - created stream session %p", this, m_streamSession.get());
@@ -219,6 +250,24 @@
m_sourceBuffers.remove(m_sourceBuffers.find(sourceBuffer));
}
+PassRefPtr<Uint8Array> CDMSessionMediaSourceAVFObjC::generateKeyReleaseMessage(unsigned short& errorCode, unsigned long& systemCode)
+{
+ ASSERT(m_mode == KeyRelease);
+ m_certificate = m_initData;
+ RetainPtr<NSData> certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate->data() length:m_certificate->length()]);
+
+ NSArray* expiredSessions = [getAVStreamSessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get()];
+ if (![expiredSessions count]) {
+ errorCode = MediaPlayer::KeySystemNotSupported;
+ return nullptr;
+ }
+
+ errorCode = 0;
+ systemCode = 0;
+ m_expiredSession = [expiredSessions firstObject];
+ return Uint8Array::create(static_cast<const uint8_t*>([m_expiredSession bytes]), [m_expiredSession length]);
}
+}
+
#endif