Changeset 220959 in webkit


Ignore:
Timestamp:
Aug 20, 2017 11:21:38 PM (7 years ago)
Author:
zandobersek@gmail.com
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.

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r220955 r220959  
     12017-08-20  Zan Dobersek  <zdobersek@igalia.com>
     2
     3        [EME] Add basic implementation of HTMLMediaElement::setMediaKeys()
     4        https://bugs.webkit.org/show_bug.cgi?id=175717
     5
     6        Reviewed by Xabier Rodriguez-Calvar.
     7
     8        * platform/wpe/imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-expected.txt:
     9        Update the baseline, with the test no longer timing out but instead
     10        failing with a NotAllowed exception thrown.
     11
    1122017-08-19  Andy Estes  <aestes@apple.com>
    213
  • trunk/LayoutTests/platform/wpe/imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-expected.txt

    r220269 r220959  
    11
    2 Harness Error (TIMEOUT), message = null
     2FAIL 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
    33
    4 TIMEOUT org.w3.clearkey, setMediaKeys Test timed out
    5 
  • trunk/Source/WebCore/ChangeLog

    r220957 r220959  
     12017-08-20  Zan Dobersek  <zdobersek@igalia.com>
     2
     3        [EME] Add basic implementation of HTMLMediaElement::setMediaKeys()
     4        https://bugs.webkit.org/show_bug.cgi?id=175717
     5
     6        Reviewed by Xabier Rodriguez-Calvar.
     7
     8        Add an initial and incomplete implementation of HTMLMediaElement::setMediaKeys(),
     9        interleaved with the specification wording of how this operation should behave.
     10        The implementation still doesn't cover cases of CDM instances being already
     11        associated with a different HTMLMediaElement, of CDM instances that can't be
     12        disassociated from the current HTMLMediaElement, and of failures during both
     13        association and disassociation of MediaKeys with the HTMLMediaElement.
     14
     15        The HTMLMediaElement (as a CDMClient inheritor) has to be attached or detached
     16        from the MediaKeys object as appropriate. This attachment allows MediaKeys to
     17        initiate an attempt to resume playback whenever the key statuses of the
     18        associated MediaKeys object are updated.
     19
     20        Upon association and disassociation with MediaKeys, the CDMInstance object of
     21        that specific MediaKeys instance is attached to or detached from the MediaPlayer
     22        instance. This allows the platform layer to gather information about the
     23        CDMInstance that will be used for decryption of media content for this specific
     24        media element.
     25
     26        Additionally, the detachment from both MediaKeys and MediaPlayer is done upon
     27        HTMLMediaElement destruction.
     28
     29        Upon setting the MediaKeys object, a task is queued that launches the 'Attempt to
     30        Resume Playback If Necessary' algorithm. A placeholder method is added that will
     31        implement the algorithm in the future.
     32
     33        The HTMLMediaElement::mediaKeys() getter is also implemented, returning pointer
     34        held in m_mediaKeys.
     35
     36        Covered to a degree by existing imported W3C tests, with a setMediaKeys()-oriented
     37        test having WPE-specific baseline update.
     38
     39        * Modules/encryptedmedia/MediaKeys.h:
     40        (WebCore::MediaKeys::cdmInstance const):
     41        * html/HTMLMediaElement.cpp:
     42        (WebCore::HTMLMediaElement::~HTMLMediaElement):
     43        (WebCore::HTMLMediaElement::mediaKeys const):
     44        (WebCore::HTMLMediaElement::setMediaKeys):
     45        (WebCore::HTMLMediaElement::attemptToResumePlaybackIfNecessary):
     46        (WebCore::HTMLMediaElement::contextDestroyed):
     47        * html/HTMLMediaElement.h:
     48        * platform/graphics/MediaPlayer.cpp:
     49        (WebCore::MediaPlayer::cdmInstanceAttached):
     50        (WebCore::MediaPlayer::cdmInstanceDetached):
     51        * platform/graphics/MediaPlayer.h:
     52        * platform/graphics/MediaPlayerPrivate.h:
     53        (WebCore::MediaPlayerPrivateInterface::cdmInstanceAttached):
     54        (WebCore::MediaPlayerPrivateInterface::cdmInstanceDetached):
     55
    1562017-08-20  Chris Dumez  <cdumez@apple.com>
    257
  • trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.h

    r220905 r220959  
    6464    void attemptToResumePlaybackOnClients();
    6565
     66    const CDMInstance& cdmInstance() const { return m_instance; }
     67
    6668protected:
    6769    MediaKeys(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>&, Ref<CDM>&&, Ref<CDMInstance>&&);
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r220905 r220959  
    146146#endif
    147147
     148#if ENABLE(ENCRYPTED_MEDIA)
     149#include "MediaKeys.h"
     150#endif
     151
    148152#if ENABLE(MEDIA_CONTROLS_SCRIPT)
    149153#include "JSMediaControlsHost.h"
     
    564568#endif
    565569
     570#if ENABLE(ENCRYPTED_MEDIA)
     571    if (m_mediaKeys) {
     572        m_mediaKeys->detachCDMClient(*this);
     573        if (m_player)
     574            m_player->cdmInstanceDetached(m_mediaKeys->cdmInstance());
     575    }
     576#endif
     577
    566578#if ENABLE(MEDIA_CONTROLS_SCRIPT)
    567579    if (m_isolatedWorld)
     
    584596    m_playbackControlsManagerBehaviorRestrictionsQueue.close();
    585597    m_resourceSelectionTaskQueue.close();
     598#if ENABLE(ENCRYPTED_MEDIA)
     599    m_encryptedMediaQueue.close();
     600#endif
    586601
    587602    m_completelyLoaded = true;
     
    25582573MediaKeys* HTMLMediaElement::mediaKeys() const
    25592574{
    2560     return nullptr;
    2561 }
    2562 
    2563 void HTMLMediaElement::setMediaKeys(MediaKeys*, Ref<DeferredPromise>&&)
    2564 {
     2575    return m_mediaKeys.get();
     2576}
     2577
     2578void HTMLMediaElement::setMediaKeys(MediaKeys* mediaKeys, Ref<DeferredPromise>&& promise)
     2579{
     2580    // https://w3c.github.io/encrypted-media/#dom-htmlmediaelement-setmediakeys
     2581    // W3C Editor's Draft 23 June 2017
     2582
     2583    // 1. If this object's attaching media keys value is true, return a promise rejected with an InvalidStateError.
     2584    if (m_attachingMediaKeys) {
     2585        promise->reject(InvalidStateError);
     2586        return;
     2587    }
     2588
     2589    // 2. If mediaKeys and the mediaKeys attribute are the same object, return a resolved promise.
     2590    if (mediaKeys == m_mediaKeys) {
     2591        promise->resolve();
     2592        return;
     2593    }
     2594
     2595    // 3. Let this object's attaching media keys value be true.
     2596    m_attachingMediaKeys = true;
     2597
     2598    // 4. Let promise be a new promise.
     2599    // 5. Run the following steps in parallel:
     2600    m_encryptedMediaQueue.enqueueTask([this, mediaKeys = RefPtr<MediaKeys>(mediaKeys), promise = WTFMove(promise)]() mutable {
     2601        // 5.1. If all the following conditions hold:
     2602        //      - mediaKeys is not null,
     2603        //      - the CDM instance represented by mediaKeys is already in use by another media element
     2604        //      - the user agent is unable to use it with this element
     2605        //      then let this object's attaching media keys value be false and reject promise with a QuotaExceededError.
     2606        // FIXME: ^
     2607
     2608        // 5.2. If the mediaKeys attribute is not null, run the following steps:
     2609        if (m_mediaKeys) {
     2610            // 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.
     2611            // 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.
     2612            // 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.
     2613            // 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.
     2614            // FIXME: ^
     2615
     2616            m_mediaKeys->detachCDMClient(*this);
     2617            if (m_player)
     2618                m_player->cdmInstanceDetached(m_mediaKeys->cdmInstance());
     2619        }
     2620
     2621        // 5.3. If mediaKeys is not null, run the following steps:
     2622        if (mediaKeys) {
     2623            // 5.3.1. Associate the CDM instance represented by mediaKeys with the media element for decrypting media data.
     2624            mediaKeys->attachCDMClient(*this);
     2625            if (m_player)
     2626                m_player->cdmInstanceAttached(m_mediaKeys->cdmInstance());
     2627
     2628            // 5.3.2. If the preceding step failed, run the following steps:
     2629            //   5.3.2.1. Set the mediaKeys attribute to null.
     2630            //   5.3.2.2. Let this object's attaching media keys value be false.
     2631            //   5.3.2.3. Reject promise with a new DOMException whose name is the appropriate error name.
     2632            // FIXME: ^
     2633
     2634            // 5.3.3. Queue a task to run the Attempt to Resume Playback If Necessary algorithm on the media element.
     2635            m_encryptedMediaQueue.enqueueTask([this] {
     2636                attemptToResumePlaybackIfNecessary();
     2637            });
     2638        }
     2639
     2640        // 5.4. Set the mediaKeys attribute to mediaKeys.
     2641        // 5.5. Let this object's attaching media keys value be false.
     2642        // 5.6. Resolve promise.
     2643        m_mediaKeys = WTFMove(mediaKeys);
     2644        m_attachingMediaKeys = false;
     2645        promise->resolve();
     2646    });
     2647
     2648    // 6. Return promise.
     2649}
     2650
     2651void HTMLMediaElement::attemptToResumePlaybackIfNecessary()
     2652{
     2653    // https://w3c.github.io/encrypted-media/#resume-playback
     2654    // W3C Editor's Draft 23 June 2017
     2655
    25652656    notImplemented();
    25662657}
     
    52895380    m_pauseAfterDetachedTaskQueue.close();
    52905381    m_updatePlaybackControlsManagerQueue.close();
     5382#if ENABLE(ENCRYPTED_MEDIA)
     5383    m_encryptedMediaQueue.close();
     5384#endif
    52915385
    52925386    m_pendingPlayPromises.clear();
  • trunk/Source/WebCore/html/HTMLMediaElement.h

    r220905 r220959  
    637637
    638638#if ENABLE(ENCRYPTED_MEDIA)
     639    void attemptToResumePlaybackIfNecessary();
     640
    639641    // CDMClient
    640642    void cdmClientAttemptToResumePlaybackIfNecessary() override;
     
    10921094    RefPtr<WebKitMediaKeys> m_webKitMediaKeys;
    10931095#endif
     1096#if ENABLE(ENCRYPTED_MEDIA)
     1097    RefPtr<MediaKeys> m_mediaKeys;
     1098    bool m_attachingMediaKeys { false };
     1099    GenericTaskQueue<Timer> m_encryptedMediaQueue;
     1100#endif
    10941101
    10951102    std::unique_ptr<MediaElementSession> m_mediaSession;
  • trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp

    r219526 r220959  
    585585#endif
    586586   
     587#if ENABLE(ENCRYPTED_MEDIA)
     588void MediaPlayer::cdmInstanceAttached(const CDMInstance& instance)
     589{
     590    m_private->cdmInstanceAttached(instance);
     591}
     592
     593void MediaPlayer::cdmInstanceDetached(const CDMInstance& instance)
     594{
     595    m_private->cdmInstanceDetached(instance);
     596}
     597#endif
     598
    587599MediaTime MediaPlayer::duration() const
    588600{
  • trunk/Source/WebCore/platform/graphics/MediaPlayer.h

    r219526 r220959  
    7272class AudioSourceProvider;
    7373class AuthenticationChallenge;
     74#if ENABLE(ENCRYPTED_MEDIA)
     75class CDMInstance;
     76#endif
    7477class MediaPlaybackTarget;
    7578#if ENABLE(MEDIA_SOURCE)
     
    366369#endif
    367370
     371#if ENABLE(ENCRYPTED_MEDIA)
     372    void cdmInstanceAttached(const CDMInstance&);
     373    void cdmInstanceDetached(const CDMInstance&);
     374#endif
     375
    368376    bool paused() const;
    369377    bool seeking() const;
  • trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h

    r218501 r220959  
    237237#endif
    238238
     239#if ENABLE(ENCRYPTED_MEDIA)
     240    virtual void cdmInstanceAttached(const CDMInstance&) { }
     241    virtual void cdmInstanceDetached(const CDMInstance&) { }
     242#endif
     243
    239244#if ENABLE(VIDEO_TRACK)
    240245    virtual bool requiresTextTrackRepresentation() const { return false; }
Note: See TracChangeset for help on using the changeset viewer.