Title: [220959] trunk
Revision
220959
Author
zandober...@gmail.com
Date
2017-08-20 23:21:38 -0700 (Sun, 20 Aug 2017)

Log Message

[EME] Add basic implementation of HTMLMediaElement::setMediaKeys()
https://bugs.webkit.org/show_bug.cgi?id=175717

Reviewed by Xabier Rodriguez-Calvar.

Source/WebCore:

Add an initial and incomplete implementation of HTMLMediaElement::setMediaKeys(),
interleaved with the specification wording of how this operation should behave.
The implementation still doesn't cover cases of CDM instances being already
associated with a different HTMLMediaElement, of CDM instances that can't be
disassociated from the current HTMLMediaElement, and of failures during both
association and disassociation of MediaKeys with the HTMLMediaElement.

The HTMLMediaElement (as a CDMClient inheritor) has to be attached or detached
from the MediaKeys object as appropriate. This attachment allows MediaKeys to
initiate an attempt to resume playback whenever the key statuses of the
associated MediaKeys object are updated.

Upon association and disassociation with MediaKeys, the CDMInstance object of
that specific MediaKeys instance is attached to or detached from the MediaPlayer
instance. This allows the platform layer to gather information about the
CDMInstance that will be used for decryption of media content for this specific
media element.

Additionally, the detachment from both MediaKeys and MediaPlayer is done upon
HTMLMediaElement destruction.

Upon setting the MediaKeys object, a task is queued that launches the 'Attempt to
Resume Playback If Necessary' algorithm. A placeholder method is added that will
implement the algorithm in the future.

The HTMLMediaElement::mediaKeys() getter is also implemented, returning pointer
held in m_mediaKeys.

Covered to a degree by existing imported W3C tests, with a setMediaKeys()-oriented
test having WPE-specific baseline update.

* Modules/encryptedmedia/MediaKeys.h:
(WebCore::MediaKeys::cdmInstance const):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::~HTMLMediaElement):
(WebCore::HTMLMediaElement::mediaKeys const):
(WebCore::HTMLMediaElement::setMediaKeys):
(WebCore::HTMLMediaElement::attemptToResumePlaybackIfNecessary):
(WebCore::HTMLMediaElement::contextDestroyed):
* html/HTMLMediaElement.h:
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::cdmInstanceAttached):
(WebCore::MediaPlayer::cdmInstanceDetached):
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::cdmInstanceAttached):
(WebCore::MediaPlayerPrivateInterface::cdmInstanceDetached):

LayoutTests:

* platform/wpe/imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-expected.txt:
Update the baseline, with the test no longer timing out but instead
failing with a NotAllowed exception thrown.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (220958 => 220959)


--- trunk/LayoutTests/ChangeLog	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/LayoutTests/ChangeLog	2017-08-21 06:21:38 UTC (rev 220959)
@@ -1,3 +1,14 @@
+2017-08-20  Zan Dobersek  <zdober...@igalia.com>
+
+        [EME] Add basic implementation of HTMLMediaElement::setMediaKeys()
+        https://bugs.webkit.org/show_bug.cgi?id=175717
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        * platform/wpe/imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-expected.txt:
+        Update the baseline, with the test no longer timing out but instead
+        failing with a NotAllowed exception thrown.
+
 2017-08-19  Andy Estes  <aes...@apple.com>
 
         [Payment Request] Add interface stubs

Modified: trunk/LayoutTests/platform/wpe/imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-expected.txt (220958 => 220959)


--- trunk/LayoutTests/platform/wpe/imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-expected.txt	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/LayoutTests/platform/wpe/imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-expected.txt	2017-08-21 06:21:38 UTC (rev 220959)
@@ -1,5 +1,3 @@
 
-Harness Error (TIMEOUT), message = null
+FAIL org.w3.clearkey, setMediaKeys assert_unreached: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission. Reached unreachable code
 
-TIMEOUT org.w3.clearkey, setMediaKeys Test timed out
-

Modified: trunk/Source/WebCore/ChangeLog (220958 => 220959)


--- trunk/Source/WebCore/ChangeLog	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/Source/WebCore/ChangeLog	2017-08-21 06:21:38 UTC (rev 220959)
@@ -1,3 +1,58 @@
+2017-08-20  Zan Dobersek  <zdober...@igalia.com>
+
+        [EME] Add basic implementation of HTMLMediaElement::setMediaKeys()
+        https://bugs.webkit.org/show_bug.cgi?id=175717
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Add an initial and incomplete implementation of HTMLMediaElement::setMediaKeys(),
+        interleaved with the specification wording of how this operation should behave.
+        The implementation still doesn't cover cases of CDM instances being already
+        associated with a different HTMLMediaElement, of CDM instances that can't be
+        disassociated from the current HTMLMediaElement, and of failures during both
+        association and disassociation of MediaKeys with the HTMLMediaElement.
+
+        The HTMLMediaElement (as a CDMClient inheritor) has to be attached or detached
+        from the MediaKeys object as appropriate. This attachment allows MediaKeys to
+        initiate an attempt to resume playback whenever the key statuses of the
+        associated MediaKeys object are updated.
+
+        Upon association and disassociation with MediaKeys, the CDMInstance object of
+        that specific MediaKeys instance is attached to or detached from the MediaPlayer
+        instance. This allows the platform layer to gather information about the
+        CDMInstance that will be used for decryption of media content for this specific
+        media element.
+
+        Additionally, the detachment from both MediaKeys and MediaPlayer is done upon
+        HTMLMediaElement destruction.
+
+        Upon setting the MediaKeys object, a task is queued that launches the 'Attempt to
+        Resume Playback If Necessary' algorithm. A placeholder method is added that will
+        implement the algorithm in the future.
+
+        The HTMLMediaElement::mediaKeys() getter is also implemented, returning pointer
+        held in m_mediaKeys.
+
+        Covered to a degree by existing imported W3C tests, with a setMediaKeys()-oriented
+        test having WPE-specific baseline update.
+
+        * Modules/encryptedmedia/MediaKeys.h:
+        (WebCore::MediaKeys::cdmInstance const):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::~HTMLMediaElement):
+        (WebCore::HTMLMediaElement::mediaKeys const):
+        (WebCore::HTMLMediaElement::setMediaKeys):
+        (WebCore::HTMLMediaElement::attemptToResumePlaybackIfNecessary):
+        (WebCore::HTMLMediaElement::contextDestroyed):
+        * html/HTMLMediaElement.h:
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::cdmInstanceAttached):
+        (WebCore::MediaPlayer::cdmInstanceDetached):
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::cdmInstanceAttached):
+        (WebCore::MediaPlayerPrivateInterface::cdmInstanceDetached):
+
 2017-08-20  Chris Dumez  <cdu...@apple.com>
 
         Simplify calls to LoaderStrategy::startPingLoad()

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.h (220958 => 220959)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.h	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.h	2017-08-21 06:21:38 UTC (rev 220959)
@@ -63,6 +63,8 @@
     void detachCDMClient(CDMClient&);
     void attemptToResumePlaybackOnClients();
 
+    const CDMInstance& cdmInstance() const { return m_instance; }
+
 protected:
     MediaKeys(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>&, Ref<CDM>&&, Ref<CDMInstance>&&);
 

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (220958 => 220959)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2017-08-21 06:21:38 UTC (rev 220959)
@@ -145,6 +145,10 @@
 #include "WebKitMediaKeys.h"
 #endif
 
+#if ENABLE(ENCRYPTED_MEDIA)
+#include "MediaKeys.h"
+#endif
+
 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
 #include "JSMediaControlsHost.h"
 #include "MediaControlsHost.h"
@@ -563,6 +567,14 @@
     webkitSetMediaKeys(nullptr);
 #endif
 
+#if ENABLE(ENCRYPTED_MEDIA)
+    if (m_mediaKeys) {
+        m_mediaKeys->detachCDMClient(*this);
+        if (m_player)
+            m_player->cdmInstanceDetached(m_mediaKeys->cdmInstance());
+    }
+#endif
+
 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
     if (m_isolatedWorld)
         m_isolatedWorld->clearWrappers();
@@ -583,6 +595,9 @@
     m_updatePlaybackControlsManagerQueue.close();
     m_playbackControlsManagerBehaviorRestrictionsQueue.close();
     m_resourceSelectionTaskQueue.close();
+#if ENABLE(ENCRYPTED_MEDIA)
+    m_encryptedMediaQueue.close();
+#endif
 
     m_completelyLoaded = true;
 
@@ -2557,11 +2572,87 @@
 
 MediaKeys* HTMLMediaElement::mediaKeys() const
 {
-    return nullptr;
+    return m_mediaKeys.get();
 }
 
-void HTMLMediaElement::setMediaKeys(MediaKeys*, Ref<DeferredPromise>&&)
+void HTMLMediaElement::setMediaKeys(MediaKeys* mediaKeys, Ref<DeferredPromise>&& promise)
 {
+    // https://w3c.github.io/encrypted-media/#dom-htmlmediaelement-setmediakeys
+    // W3C Editor's Draft 23 June 2017
+
+    // 1. If this object's attaching media keys value is true, return a promise rejected with an InvalidStateError.
+    if (m_attachingMediaKeys) {
+        promise->reject(InvalidStateError);
+        return;
+    }
+
+    // 2. If mediaKeys and the mediaKeys attribute are the same object, return a resolved promise.
+    if (mediaKeys == m_mediaKeys) {
+        promise->resolve();
+        return;
+    }
+
+    // 3. Let this object's attaching media keys value be true.
+    m_attachingMediaKeys = true;
+
+    // 4. Let promise be a new promise.
+    // 5. Run the following steps in parallel:
+    m_encryptedMediaQueue.enqueueTask([this, mediaKeys = RefPtr<MediaKeys>(mediaKeys), promise = WTFMove(promise)]() mutable {
+        // 5.1. If all the following conditions hold:
+        //      - mediaKeys is not null,
+        //      - the CDM instance represented by mediaKeys is already in use by another media element
+        //      - the user agent is unable to use it with this element
+        //      then let this object's attaching media keys value be false and reject promise with a QuotaExceededError.
+        // FIXME: ^
+
+        // 5.2. If the mediaKeys attribute is not null, run the following steps:
+        if (m_mediaKeys) {
+            // 5.2.1. If the user agent or CDM do not support removing the association, let this object's attaching media keys value be false and reject promise with a NotSupportedError.
+            // 5.2.2. If the association cannot currently be removed, let this object's attaching media keys value be false and reject promise with an InvalidStateError.
+            // 5.2.3. Stop using the CDM instance represented by the mediaKeys attribute to decrypt media data and remove the association with the media element.
+            // 5.2.4. If the preceding step failed, let this object's attaching media keys value be false and reject promise with the appropriate error name.
+            // FIXME: ^
+
+            m_mediaKeys->detachCDMClient(*this);
+            if (m_player)
+                m_player->cdmInstanceDetached(m_mediaKeys->cdmInstance());
+        }
+
+        // 5.3. If mediaKeys is not null, run the following steps:
+        if (mediaKeys) {
+            // 5.3.1. Associate the CDM instance represented by mediaKeys with the media element for decrypting media data.
+            mediaKeys->attachCDMClient(*this);
+            if (m_player)
+                m_player->cdmInstanceAttached(m_mediaKeys->cdmInstance());
+
+            // 5.3.2. If the preceding step failed, run the following steps:
+            //   5.3.2.1. Set the mediaKeys attribute to null.
+            //   5.3.2.2. Let this object's attaching media keys value be false.
+            //   5.3.2.3. Reject promise with a new DOMException whose name is the appropriate error name.
+            // FIXME: ^
+
+            // 5.3.3. Queue a task to run the Attempt to Resume Playback If Necessary algorithm on the media element.
+            m_encryptedMediaQueue.enqueueTask([this] {
+                attemptToResumePlaybackIfNecessary();
+            });
+        }
+
+        // 5.4. Set the mediaKeys attribute to mediaKeys.
+        // 5.5. Let this object's attaching media keys value be false.
+        // 5.6. Resolve promise.
+        m_mediaKeys = WTFMove(mediaKeys);
+        m_attachingMediaKeys = false;
+        promise->resolve();
+    });
+
+    // 6. Return promise.
+}
+
+void HTMLMediaElement::attemptToResumePlaybackIfNecessary()
+{
+    // https://w3c.github.io/encrypted-media/#resume-playback
+    // W3C Editor's Draft 23 June 2017
+
     notImplemented();
 }
 
@@ -5288,6 +5379,9 @@
     m_promiseTaskQueue.close();
     m_pauseAfterDetachedTaskQueue.close();
     m_updatePlaybackControlsManagerQueue.close();
+#if ENABLE(ENCRYPTED_MEDIA)
+    m_encryptedMediaQueue.close();
+#endif
 
     m_pendingPlayPromises.clear();
 

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (220958 => 220959)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2017-08-21 06:21:38 UTC (rev 220959)
@@ -636,6 +636,8 @@
 #endif
 
 #if ENABLE(ENCRYPTED_MEDIA)
+    void attemptToResumePlaybackIfNecessary();
+
     // CDMClient
     void cdmClientAttemptToResumePlaybackIfNecessary() override;
 #endif
@@ -1091,6 +1093,11 @@
 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
     RefPtr<WebKitMediaKeys> m_webKitMediaKeys;
 #endif
+#if ENABLE(ENCRYPTED_MEDIA)
+    RefPtr<MediaKeys> m_mediaKeys;
+    bool m_attachingMediaKeys { false };
+    GenericTaskQueue<Timer> m_encryptedMediaQueue;
+#endif
 
     std::unique_ptr<MediaElementSession> m_mediaSession;
     size_t m_reportedExtraMemoryCost { 0 };

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (220958 => 220959)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2017-08-21 06:21:38 UTC (rev 220959)
@@ -584,6 +584,18 @@
 }
 #endif
     
+#if ENABLE(ENCRYPTED_MEDIA)
+void MediaPlayer::cdmInstanceAttached(const CDMInstance& instance)
+{
+    m_private->cdmInstanceAttached(instance);
+}
+
+void MediaPlayer::cdmInstanceDetached(const CDMInstance& instance)
+{
+    m_private->cdmInstanceDetached(instance);
+}
+#endif
+
 MediaTime MediaPlayer::duration() const
 {
     return m_private->durationMediaTime();

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (220958 => 220959)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2017-08-21 06:21:38 UTC (rev 220959)
@@ -71,6 +71,9 @@
 
 class AudioSourceProvider;
 class AuthenticationChallenge;
+#if ENABLE(ENCRYPTED_MEDIA)
+class CDMInstance;
+#endif
 class MediaPlaybackTarget;
 #if ENABLE(MEDIA_SOURCE)
 class MediaSourcePrivateClient;
@@ -365,6 +368,11 @@
     void keyAdded();
 #endif
 
+#if ENABLE(ENCRYPTED_MEDIA)
+    void cdmInstanceAttached(const CDMInstance&);
+    void cdmInstanceDetached(const CDMInstance&);
+#endif
+
     bool paused() const;
     bool seeking() const;
 

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (220958 => 220959)


--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2017-08-21 04:26:40 UTC (rev 220958)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2017-08-21 06:21:38 UTC (rev 220959)
@@ -236,6 +236,11 @@
     virtual void keyAdded() { }
 #endif
 
+#if ENABLE(ENCRYPTED_MEDIA)
+    virtual void cdmInstanceAttached(const CDMInstance&) { }
+    virtual void cdmInstanceDetached(const CDMInstance&) { }
+#endif
+
 #if ENABLE(VIDEO_TRACK)
     virtual bool requiresTextTrackRepresentation() const { return false; }
     virtual void setTextTrackRepresentation(TextTrackRepresentation*) { }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to