[EME] Implement MediaKeys.isTypeSupported()
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Aug 2013 19:17:47 +0000 (19:17 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Aug 2013 19:17:47 +0000 (19:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=119586

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/encrypted-media/encrypted-media-is-type-supported.html

The EME spec has removed the extra keySystem parameter from
HTMLMediaElement.canPlayType() in favor of a new isTypeSupported()
method on MediaKeys.

To implement this method, the CDMFactory needs to know whether the
registered CDM supports the specified mime type.  CDMs must register
this new factory method, which requires changes to CDMPrivateAVFoundation
and MockCDM.

Add the new MediaKeys.isTypeSupported() method:
* Modules/encryptedmedia/MediaKeys.cpp:
(WebCore::MediaKeys::isTypeSupported):
* Modules/encryptedmedia/MediaKeys.h:
* Modules/encryptedmedia/MediaKeys.idl:

Add the new factory CDMSupportsKeySystemAndMimeType method:
* Modules/encryptedmedia/CDM.cpp:
(WebCore::CDMFactory::CDMFactory): Now takes a third parameter.
(WebCore::installedCDMFactories): When adding the AVFoundation CDM, pass its new method.
(WebCore::CDM::registerCDMFactory): Now takes a third parameter.
(WebCore::CDM::keySystemSupportsMimeType): Added.
* Modules/encryptedmedia/CDM.h:
* WebCore.exp.in:

Register this new method with the factory for all concrete CDMs:
* Modules/encryptedmedia/CDMPrivateAVFoundation.h:
* Modules/encryptedmedia/CDMPrivateAVFoundation.mm:
(WebCore::CDMPrivateAVFoundation::supportsKeySystem):
(WebCore::CDMPrivateAVFoundation::supportsKeySystemAndMimeType):
* testing/Internals.cpp:
(WebCore::Internals::initializeMockCDM):
* testing/MockCDM.cpp:
(WebCore::MockCDM::supportsKeySystem):
(WebCore::MockCDM::supportsKeySystemAndMimeType):
* testing/MockCDM.h:

LayoutTests:

* media/encrypted-media/encrypted-media-is-type-supported-expected.txt: Added.
* media/encrypted-media/encrypted-media-is-type-supported.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@153838 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/media/encrypted-media/encrypted-media-is-type-supported-expected.txt [new file with mode: 0644]
LayoutTests/media/encrypted-media/encrypted-media-is-type-supported.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/encryptedmedia/CDM.cpp
Source/WebCore/Modules/encryptedmedia/CDM.h
Source/WebCore/Modules/encryptedmedia/CDMPrivateAVFoundation.h
Source/WebCore/Modules/encryptedmedia/CDMPrivateAVFoundation.mm
Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp
Source/WebCore/Modules/encryptedmedia/MediaKeys.h
Source/WebCore/Modules/encryptedmedia/MediaKeys.idl
Source/WebCore/WebCore.exp.in
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/MockCDM.cpp
Source/WebCore/testing/MockCDM.h

index 7c4c9e9..f1e7b04 100644 (file)
@@ -1,3 +1,13 @@
+2013-08-08  Jer Noble  <jer.noble@apple.com>
+
+        [EME] Implement MediaKeys.isTypeSupported()
+        https://bugs.webkit.org/show_bug.cgi?id=119586
+
+        Reviewed by Eric Carlson.
+
+        * media/encrypted-media/encrypted-media-is-type-supported-expected.txt: Added.
+        * media/encrypted-media/encrypted-media-is-type-supported.html: Added.
+
 2013-08-08  Eric Carlson  <eric.carlson@apple.com>
 
         fast/events/scroll-div-with-prevent-default-in-subframe.html is failing
diff --git a/LayoutTests/media/encrypted-media/encrypted-media-is-type-supported-expected.txt b/LayoutTests/media/encrypted-media/encrypted-media-is-type-supported-expected.txt
new file mode 100644 (file)
index 0000000..16eb982
--- /dev/null
@@ -0,0 +1,22 @@
+Test Encrypted Media extension of MediaKeys isTypeSupported() method.
+
+Always return false for a null type.
+EXPECTED (MediaKeys.isTypeSupported(null) == 'false') OK
+
+Always return false for an empty type.
+EXPECTED (MediaKeys.isTypeSupported('') == 'false') OK
+EXPECTED (MediaKeys.isTypeSupported('', '') == 'false') OK
+EXPECTED (MediaKeys.isTypeSupported('', null) == 'false') OK
+EXPECTED (MediaKeys.isTypeSupported('', undefined) == 'false') OK
+EXPECTED (MediaKeys.isTypeSupported('', 'video/invalid') == 'false') OK
+
+Always return true for supported types.
+EXPECTED (MediaKeys.isTypeSupported('com.webcore.mock') == 'true') OK
+
+Always return true for supported types and containers.
+EXPECTED (MediaKeys.isTypeSupported('com.webcore.mock', 'video/mock') == 'true') OK
+
+Always return false for supported types but unsupported containers.
+EXPECTED (MediaKeys.isTypeSupported('com.webcore.mock', 'video/invalid') == 'false') OK
+END OF TEST
+
diff --git a/LayoutTests/media/encrypted-media/encrypted-media-is-type-supported.html b/LayoutTests/media/encrypted-media/encrypted-media-is-type-supported.html
new file mode 100644 (file)
index 0000000..84088c3
--- /dev/null
@@ -0,0 +1,40 @@
+<!doctype html>
+<html lang="en">
+    <head>
+        <title>MediaKeys.isTypeSupported()</title>
+        <script src=../video-test.js></script>
+        <script>
+            // Initialize the MockCDM. It supports the key system 'com.webcore.mock', the 
+            // mime type 'video/mock'. It requires init data to begin with 'mock', and
+            // keys to begin with 'key'.
+            if (internals)
+                internals.initializeMockCDM();
+
+            function runTest() {
+                consoleWrite("Always return false for a null type.");
+                testExpected("MediaKeys.isTypeSupported(null)", false);
+
+                consoleWrite("<br>Always return false for an empty type.");
+                testExpected("MediaKeys.isTypeSupported('')", false);
+                testExpected("MediaKeys.isTypeSupported('', '')", false);
+                testExpected("MediaKeys.isTypeSupported('', null)", false);
+                testExpected("MediaKeys.isTypeSupported('', undefined)", false);
+                testExpected("MediaKeys.isTypeSupported('', 'video/invalid')", false);
+
+                consoleWrite("<br>Always return true for supported types.");
+                testExpected("MediaKeys.isTypeSupported('com.webcore.mock')", true);
+
+                consoleWrite("<br>Always return true for supported types and containers.");
+                testExpected("MediaKeys.isTypeSupported('com.webcore.mock', 'video/mock')", true);
+
+                consoleWrite("<br>Always return false for supported types but unsupported containers.");
+                testExpected("MediaKeys.isTypeSupported('com.webcore.mock', 'video/invalid')", false);
+
+                endTest();
+            }
+        </script>
+    </head>
+    <body onload="runTest()">
+        <p>Test Encrypted Media extension of MediaKeys <em>isTypeSupported()</em> method.</p>
+    </body>
+</html>
index e54e103..c5eb7c2 100644 (file)
@@ -1,3 +1,48 @@
+2013-08-08  Jer Noble  <jer.noble@apple.com>
+
+        [EME] Implement MediaKeys.isTypeSupported()
+        https://bugs.webkit.org/show_bug.cgi?id=119586
+
+        Reviewed by Eric Carlson.
+
+        Test: media/encrypted-media/encrypted-media-is-type-supported.html
+
+        The EME spec has removed the extra keySystem parameter from
+        HTMLMediaElement.canPlayType() in favor of a new isTypeSupported()
+        method on MediaKeys.
+
+        To implement this method, the CDMFactory needs to know whether the
+        registered CDM supports the specified mime type.  CDMs must register
+        this new factory method, which requires changes to CDMPrivateAVFoundation
+        and MockCDM.
+
+        Add the new MediaKeys.isTypeSupported() method:
+        * Modules/encryptedmedia/MediaKeys.cpp:
+        (WebCore::MediaKeys::isTypeSupported):
+        * Modules/encryptedmedia/MediaKeys.h:
+        * Modules/encryptedmedia/MediaKeys.idl:
+
+        Add the new factory CDMSupportsKeySystemAndMimeType method:
+        * Modules/encryptedmedia/CDM.cpp:
+        (WebCore::CDMFactory::CDMFactory): Now takes a third parameter.
+        (WebCore::installedCDMFactories): When adding the AVFoundation CDM, pass its new method.
+        (WebCore::CDM::registerCDMFactory): Now takes a third parameter.
+        (WebCore::CDM::keySystemSupportsMimeType): Added.
+        * Modules/encryptedmedia/CDM.h:
+        * WebCore.exp.in:
+
+        Register this new method with the factory for all concrete CDMs:
+        * Modules/encryptedmedia/CDMPrivateAVFoundation.h:
+        * Modules/encryptedmedia/CDMPrivateAVFoundation.mm:
+        (WebCore::CDMPrivateAVFoundation::supportsKeySystem):
+        (WebCore::CDMPrivateAVFoundation::supportsKeySystemAndMimeType):
+        * testing/Internals.cpp:
+        (WebCore::Internals::initializeMockCDM):
+        * testing/MockCDM.cpp:
+        (WebCore::MockCDM::supportsKeySystem):
+        (WebCore::MockCDM::supportsKeySystemAndMimeType):
+        * testing/MockCDM.h:
+
 2013-08-08  Rob Buis  <rwlbuis@webkit.org>
 
         Crash in WTF::RefPtr<WebCore::SpaceSplitStringData>::operator UnspecifiedBoolType
index 1637216..782087c 100644 (file)
@@ -43,14 +43,16 @@ namespace WebCore {
 struct CDMFactory {
     WTF_MAKE_NONCOPYABLE(CDMFactory); WTF_MAKE_FAST_ALLOCATED;
 public:
-    CDMFactory(CreateCDM constructor, CDMSupportsKeySystem supportsKeySystem)
+    CDMFactory(CreateCDM constructor, CDMSupportsKeySystem supportsKeySystem, CDMSupportsKeySystemAndMimeType supportsKeySystemAndMimeType)
         : constructor(constructor)
         , supportsKeySystem(supportsKeySystem)
+        , supportsKeySystemAndMimeType(supportsKeySystemAndMimeType)
     {
     }
 
     CreateCDM constructor;
     CDMSupportsKeySystem supportsKeySystem;
+    CDMSupportsKeySystemAndMimeType supportsKeySystemAndMimeType;
 };
 
 static Vector<CDMFactory*>& installedCDMFactories()
@@ -62,7 +64,7 @@ static Vector<CDMFactory*>& installedCDMFactories()
 
         // FIXME: initialize specific UA CDMs. http://webkit.org/b/109318, http://webkit.org/b/109320
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
-        cdms.append(new CDMFactory(CDMPrivateAVFoundation::create, CDMPrivateAVFoundation::supportsKeySytem));
+        cdms.append(new CDMFactory(CDMPrivateAVFoundation::create, CDMPrivateAVFoundation::supportsKeySystem, CDMPrivateAVFoundation::supportsKeySystemAndMimeType));
 #endif
 
     }
@@ -70,9 +72,9 @@ static Vector<CDMFactory*>& installedCDMFactories()
     return cdms;
 }
 
-void CDM::registerCDMFactory(CreateCDM constructor, CDMSupportsKeySystem supportsKeySystem)
+void CDM::registerCDMFactory(CreateCDM constructor, CDMSupportsKeySystem supportsKeySystem, CDMSupportsKeySystemAndMimeType supportsKeySystemAndMimeType)
 {
-    installedCDMFactories().append(new CDMFactory(constructor, supportsKeySystem));
+    installedCDMFactories().append(new CDMFactory(constructor, supportsKeySystem, supportsKeySystemAndMimeType));
 }
 
 static CDMFactory* CDMFactoryForKeySystem(const String& keySystem)
@@ -90,6 +92,13 @@ bool CDM::supportsKeySystem(const String& keySystem)
     return CDMFactoryForKeySystem(keySystem);
 }
 
+bool CDM::keySystemSupportsMimeType(const String& keySystem, const String& mimeType)
+{
+    if (CDMFactory* factory = CDMFactoryForKeySystem(keySystem))
+        return factory->supportsKeySystemAndMimeType(keySystem, mimeType);
+    return false;
+}
+
 PassOwnPtr<CDM> CDM::create(const String& keySystem)
 {
     if (!supportsKeySystem(keySystem))
index 3c40f9c..344b118 100644 (file)
@@ -42,6 +42,7 @@ class MediaPlayer;
 
 typedef PassOwnPtr<CDMPrivateInterface> (*CreateCDM)(CDM*);
 typedef bool (*CDMSupportsKeySystem)(const String&);
+typedef bool (*CDMSupportsKeySystemAndMimeType)(const String&, const String&);
 
 class CDMClient {
 public:
@@ -66,8 +67,9 @@ public:
 
     enum CDMErrorCode { UnknownError = 1, ClientError, ServiceError, OutputError, HardwareChangeError, DomainError };
     static bool supportsKeySystem(const String&);
+    static bool keySystemSupportsMimeType(const String& keySystem, const String& mimeType);
     static PassOwnPtr<CDM> create(const String& keySystem);
-    static void registerCDMFactory(CreateCDM, CDMSupportsKeySystem);
+    static void registerCDMFactory(CreateCDM, CDMSupportsKeySystem, CDMSupportsKeySystemAndMimeType);
     ~CDM();
 
     bool supportsMIMEType(const String&) const;
index 2e35343..8057f0d 100644 (file)
@@ -40,7 +40,8 @@ class CDMPrivateAVFoundation : public CDMPrivateInterface {
 public:
     // CDMFactory support:
     static PassOwnPtr<CDMPrivateInterface> create(CDM* cdm) { return adoptPtr(new CDMPrivateAVFoundation(cdm)); }
-    static bool supportsKeySytem(const String&);
+    static bool supportsKeySystem(const String&);
+    static bool supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType);
 
     virtual ~CDMPrivateAVFoundation() { }
 
index 0236cab..bb78fdc 100644 (file)
@@ -62,11 +62,18 @@ SOFT_LINK_CLASS(AVFoundation, AVAssetResourceLoadingRequest)
 #define AVAssetResourceLoadingRequest getAVAssetResourceLoadingRequest()
 
 
-bool CDMPrivateAVFoundation::supportsKeySytem(const String& keySystem)
+bool CDMPrivateAVFoundation::supportsKeySystem(const String& keySystem)
 {
     return equalIgnoringCase(keySystem, "com.apple.fps") || equalIgnoringCase(keySystem, "com.apple.fps.1_0");
 }
 
+bool CDMPrivateAVFoundation::supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType)
+{
+    if (!supportsKeySystem(keySystem))
+        return false;
+    return [AVURLAsset isPlayableExtendedMIMEType:mimeType];
+}
+
 bool CDMPrivateAVFoundation::supportsMIMEType(const String& mimeType)
 {
     return [AVURLAsset isPlayableExtendedMIMEType:mimeType];
index 5d193fb..a07bc12 100644 (file)
@@ -118,6 +118,26 @@ PassRefPtr<MediaKeySession> MediaKeys::createSession(ScriptExecutionContext* con
     return session;
 }
 
+bool MediaKeys::isTypeSupported(const String& keySystem, const String& mimeType)
+{
+    // 1. If keySystem contains an unrecognized or unsupported Key System, return false and abort these steps.
+    // Key system string comparison is case-sensitive.
+    if (keySystem.isNull() || keySystem.isEmpty() || !CDM::supportsKeySystem(keySystem))
+        return false;
+
+    // 2. If type is null or an empty string, return true and abort these steps.
+    if (mimeType.isNull() || mimeType.isEmpty())
+        return true;
+
+    // 3. If the Key System specified by keySystem does not support decrypting the container and/or codec
+    // specified by type, return false and abort these steps.
+    if (!CDM::keySystemSupportsMimeType(keySystem, mimeType))
+        return false;
+
+    // 4. Return true;
+    return true;
+}
+
 void MediaKeys::setMediaElement(HTMLMediaElement* element)
 {
     m_mediaElement = element;
index f162f96..4188495 100644 (file)
@@ -50,6 +50,8 @@ public:
 
     PassRefPtr<MediaKeySession> createSession(ScriptExecutionContext*, const String& mimeType, Uint8Array* initData, ExceptionCode&);
 
+    static bool isTypeSupported(const String& keySystem, const String& mimeType);
+
     const String& keySystem() const { return m_keySystem; }
     CDM* cdm() { return m_cdm.get(); }
 
index 6427aba..0a4ddcb 100644 (file)
@@ -30,5 +30,7 @@
 ] interface MediaKeys {
     [CallWith=ScriptExecutionContext, RaisesException] MediaKeySession createSession([Default=Undefined] optional DOMString type, [Default=Undefined] optional Uint8Array initData);
 
+    static boolean isTypeSupported(DOMString keySystem, [Default=NullString] optional DOMString type);
+
     readonly attribute DOMString keySystem;
 };
index b1ff216..ac91f05 100644 (file)
@@ -2777,7 +2777,7 @@ __ZN7WebCore22RuntimeEnabledFeatures32isLegacyCSSVendorPrefixesEnabledE
 #endif
 
 #if ENABLE(ENCRYPTED_MEDIA_V2)
-__ZN7WebCore3CDM18registerCDMFactoryEPFN3WTF10PassOwnPtrINS_19CDMPrivateInterfaceEEEPS0_EPFbRKNS1_6StringEE
+__ZN7WebCore3CDM18registerCDMFactoryEPFN3WTF10PassOwnPtrINS_19CDMPrivateInterfaceEEEPS0_EPFbRKNS1_6StringEEPFbSA_SA_E
 #endif
 
 #if ENABLE(VIDEO_TRACK)
index 4d689c0..b1cb2ee 100644 (file)
@@ -2030,7 +2030,7 @@ void Internals::forceReload(bool endToEnd)
 #if ENABLE(ENCRYPTED_MEDIA_V2)
 void Internals::initializeMockCDM()
 {
-    CDM::registerCDMFactory(MockCDM::create, MockCDM::supportsKeySytem);
+    CDM::registerCDMFactory(MockCDM::create, MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType);
 }
 #endif
 
index ad74a24..562cb57 100644 (file)
@@ -50,11 +50,19 @@ protected:
     String m_sessionId;
 };
 
-bool MockCDM::supportsKeySytem(const String& keySystem)
+bool MockCDM::supportsKeySystem(const String& keySystem)
 {
     return equalIgnoringCase(keySystem, "com.webcore.mock");
 }
 
+bool MockCDM::supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType)
+{
+    if (!supportsKeySystem(keySystem))
+        return false;
+
+    return equalIgnoringCase(mimeType, "video/mock");
+}
+
 bool MockCDM::supportsMIMEType(const String& mimeType)
 {
     return equalIgnoringCase(mimeType, "video/mock");
index 1ccc4c4..3b392db 100644 (file)
@@ -39,7 +39,8 @@ class MockCDM : public CDMPrivateInterface {
 public:
     // CDMFactory support:
     static PassOwnPtr<CDMPrivateInterface> create(CDM* cdm) { return adoptPtr(new MockCDM(cdm)); }
-    static bool supportsKeySytem(const String&);
+    static bool supportsKeySystem(const String&);
+    static bool supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType);
 
     virtual ~MockCDM() { }