1d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// found in the LICENSE file.
4d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
5d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "config.h"
6d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h"
7d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
8197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionState.h"
97242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "bindings/core/v8/ScriptPromise.h"
107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "bindings/core/v8/ScriptPromiseResolver.h"
117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "bindings/core/v8/ScriptState.h"
127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/dom/DOMException.h"
13d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/dom/ExceptionCode.h"
14d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/html/HTMLMediaElement.h"
15d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/html/MediaKeyError.h"
16d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/html/MediaKeyEvent.h"
17d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "modules/encryptedmedia/MediaKeyNeededEvent.h"
18d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "modules/encryptedmedia/MediaKeys.h"
197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "modules/encryptedmedia/SimpleContentDecryptionModuleResult.h"
207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/ContentDecryptionModuleResult.h"
21d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "platform/Logging.h"
2276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)#include "platform/RuntimeEnabledFeatures.h"
237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "wtf/Functional.h"
24197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "wtf/Uint8Array.h"
25d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
26c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
27d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
28e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)static void throwExceptionIfMediaKeyExceptionOccurred(const String& keySystem, const String& sessionId, WebMediaPlayer::MediaKeyException exception, ExceptionState& exceptionState)
29d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
30d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    switch (exception) {
31e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayer::MediaKeyExceptionNoError:
32d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
33e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState:
34d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The player is in an invalid state.");
35d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
36e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported:
37d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(NotSupportedError, "The key system provided ('" + keySystem +"') is not supported.");
38d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
39e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayer::MediaKeyExceptionInvalidAccess:
40d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, "The session ID provided ('" + sessionId + "') is invalid.");
41d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
42d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
44d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT_NOT_REACHED();
45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return;
46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
47d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// This class allows MediaKeys to be set asynchronously.
497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass SetMediaKeysHandler : public ScriptPromiseResolver {
507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_MAKE_NONCOPYABLE(SetMediaKeysHandler);
517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccipublic:
537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static ScriptPromise create(ScriptState*, HTMLMediaElement&, MediaKeys*);
547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    virtual ~SetMediaKeysHandler();
557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate:
577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    SetMediaKeysHandler(ScriptState*, HTMLMediaElement&, MediaKeys*);
587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void timerFired(Timer<SetMediaKeysHandler>*);
597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void clearExistingMediaKeys();
617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void setNewMediaKeys();
627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void finish();
637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void reportSetFailed(ExceptionCode, const String& errorMessage);
657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Keep media element alive until promise is fulfilled
677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RefPtrWillBePersistent<HTMLMediaElement> m_element;
687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Persistent<MediaKeys> m_newMediaKeys;
697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Timer<SetMediaKeysHandler> m_timer;
707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci};
717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitypedef Function<void()> SuccessCallback;
737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccitypedef Function<void(ExceptionCode, const String&)> FailureCallback;
747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Represents the result used when setContentDecryptionModule() is called.
767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Calls |success| if result is resolved, |failure| is result is rejected.
777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass SetContentDecryptionModuleResult FINAL : public ContentDecryptionModuleResult {
787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccipublic:
797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    SetContentDecryptionModuleResult(SuccessCallback success, FailureCallback failure)
807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        : m_successCallback(success)
817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        , m_failureCallback(failure)
827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // ContentDecryptionModuleResult implementation.
867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    virtual void complete() OVERRIDE
877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_successCallback();
897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    virtual void completeWithSession(blink::WebContentDecryptionModuleResult::SessionStatus status) OVERRIDE
927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT_NOT_REACHED();
947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_failureCallback(InvalidStateError, "Unexpected completion.");
957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    virtual void completeWithError(blink::WebContentDecryptionModuleException code, unsigned long systemCode, const blink::WebString& message) OVERRIDE
987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_failureCallback(WebCdmExceptionToExceptionCode(code), message);
1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
1017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate:
1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    SuccessCallback m_successCallback;
1047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    FailureCallback m_failureCallback;
1057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci};
1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciScriptPromise SetMediaKeysHandler::create(ScriptState* scriptState, HTMLMediaElement& element, MediaKeys* mediaKeys)
1087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RefPtr<SetMediaKeysHandler> handler = adoptRef(new SetMediaKeysHandler(scriptState, element, mediaKeys));
1107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    handler->suspendIfNeeded();
1117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    handler->keepAliveWhilePending();
1127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return handler->promise();
1137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciSetMediaKeysHandler::SetMediaKeysHandler(ScriptState* scriptState, HTMLMediaElement& element, MediaKeys* mediaKeys)
1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    : ScriptPromiseResolver(scriptState)
1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_element(element)
1187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_newMediaKeys(mediaKeys)
1197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_timer(this, &SetMediaKeysHandler::timerFired)
1207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_LOG(Media, "SetMediaKeysHandler::SetMediaKeysHandler");
1227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3. Run the remaining steps asynchronously.
1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_timer.startOneShot(0, FROM_HERE);
1257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciSetMediaKeysHandler::~SetMediaKeysHandler()
1287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid SetMediaKeysHandler::timerFired(Timer<SetMediaKeysHandler>*)
1327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    clearExistingMediaKeys();
1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid SetMediaKeysHandler::clearExistingMediaKeys()
1377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_LOG(Media, "SetMediaKeysHandler::clearExistingMediaKeys");
1397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(*m_element);
1407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.1 If mediaKeys is not null, it is already in use by another media
1427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //     element, and the user agent is unable to use it with this element,
1437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //     reject promise with a new DOMException whose name is
1447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //     "QuotaExceededError".
1457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: Need to check whether mediaKeys is already in use by another
1467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //        media element.
1477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.2 If the mediaKeys attribute is not null, run the following steps:
1487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (thisElement.m_mediaKeys) {
1497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 3.2.1 If the user agent or CDM do not support removing the
1507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       association, return a promise rejected with a new DOMException
1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       whose name is "NotSupportedError".
1527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       (supported by blink).
1537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 3.2.2 If the association cannot currently be removed (i.e. during
1547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       playback), return a promise rejected with a new DOMException
1557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       whose name is "InvalidStateError".
1567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (m_element->webMediaPlayer()) {
1577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            reject(DOMException::create(InvalidStateError, "The existing MediaKeys object cannot be removed while a media resource is loaded."));
1587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return;
1597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
1607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // (next 2 steps not required as there is no player connected).
1627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 3.2.3 Stop using the CDM instance represented by the mediaKeys
1637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       attribute to decrypt media data and remove the association
1647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       with the media element.
1657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 3.2.4 If the preceding step failed, reject promise with a new
1667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       DOMException whose name is the appropriate error name and
1677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       that has an appropriate message.
1687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
1697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // MediaKeys not currently set or no player connected, so continue on.
1717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    setNewMediaKeys();
1727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid SetMediaKeysHandler::setNewMediaKeys()
1757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_LOG(Media, "SetMediaKeysHandler::setNewMediaKeys");
1777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.3 If mediaKeys is not null, run the following steps:
1797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (m_newMediaKeys) {
1807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 3.3.1 Associate the CDM instance represented by mediaKeys with the
1817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       media element for decrypting media data.
1827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 3.3.2 If the preceding step failed, run the following steps:
1837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       (done in reportSetFailed()).
1847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 3.3.3 Run the Attempt to Resume Playback If Necessary algorithm on
1857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       the media element. The user agent may choose to skip this
1867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       step if it knows resuming will fail (i.e. mediaKeys has no
1877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       sessions).
1887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        //       (Handled in Chromium).
1897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (m_element->webMediaPlayer()) {
1907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            SuccessCallback successCallback = bind(&SetMediaKeysHandler::finish, this);
1917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            FailureCallback failureCallback = bind<ExceptionCode, const String&>(&SetMediaKeysHandler::reportSetFailed, this);
1927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            ContentDecryptionModuleResult* result = new SetContentDecryptionModuleResult(successCallback, failureCallback);
1937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            m_element->webMediaPlayer()->setContentDecryptionModule(m_newMediaKeys->contentDecryptionModule(), result->result());
1947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // Don't do anything more until |result| is resolved (or rejected).
1967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return;
1977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
1987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
1997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // MediaKeys doesn't need to be set on the player, so continue on.
2017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    finish();
2027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid SetMediaKeysHandler::finish()
2057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_LOG(Media, "SetMediaKeysHandler::finish");
2077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(*m_element);
2087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.4 Set the mediaKeys attribute to mediaKeys.
2107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    thisElement.m_mediaKeys = m_newMediaKeys;
2117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.5 Resolve promise with undefined.
2137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    resolve();
2147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid SetMediaKeysHandler::reportSetFailed(ExceptionCode code, const String& errorMessage)
2177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_LOG(Media, "SetMediaKeysHandler::reportSetFailed");
2197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(*m_element);
2207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.3.2 If the preceding step failed, run the following steps:
2227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.3.2.1 Set the mediaKeys attribute to null.
2237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    thisElement.m_mediaKeys.clear();
2247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3.3.2.2 Reject promise with a new DOMException whose name is the
2267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //         appropriate error name and that has an appropriate message.
2277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    reject(DOMException::create(code, errorMessage));
2287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
230d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)HTMLMediaElementEncryptedMedia::HTMLMediaElementEncryptedMedia()
231d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    : m_emeMode(EmeModeNotSelected)
232d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
233d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
234d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
235323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(HTMLMediaElementEncryptedMedia)
236d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
237d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)const char* HTMLMediaElementEncryptedMedia::supplementName()
238d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
239d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return "HTMLMediaElementEncryptedMedia";
240d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
241d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
242d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)HTMLMediaElementEncryptedMedia& HTMLMediaElementEncryptedMedia::from(HTMLMediaElement& element)
243d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
244323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    HTMLMediaElementEncryptedMedia* supplement = static_cast<HTMLMediaElementEncryptedMedia*>(WillBeHeapSupplement<HTMLMediaElement>::from(element, supplementName()));
245d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!supplement) {
246d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        supplement = new HTMLMediaElementEncryptedMedia();
247323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        provideTo(element, supplementName(), adoptPtrWillBeNoop(supplement));
248d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
249d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return *supplement;
250d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
251d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
2527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccibool HTMLMediaElementEncryptedMedia::setEmeMode(EmeMode emeMode)
253d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
2547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (m_emeMode != EmeModeNotSelected && m_emeMode != emeMode)
255d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
2567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
257d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_emeMode = emeMode;
258d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return true;
259d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
260d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
261e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryptionModule()
262d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
263d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return m_mediaKeys ? m_mediaKeys->contentDecryptionModule() : 0;
264d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
265d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
266d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)MediaKeys* HTMLMediaElementEncryptedMedia::mediaKeys(HTMLMediaElement& element)
267d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
268d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element);
269d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return thisElement.m_mediaKeys.get();
270d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
271d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
2727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciScriptPromise HTMLMediaElementEncryptedMedia::setMediaKeys(ScriptState* scriptState, HTMLMediaElement& element, MediaKeys* mediaKeys)
273d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
274d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element);
2757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::setMediaKeys current(%p), new(%p)", thisElement.m_mediaKeys.get(), mediaKeys);
276d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
2777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!thisElement.setEmeMode(EmeModeUnprefixed))
2787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Mixed use of EME prefixed and unprefixed API not allowed."));
279d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
2807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 1. If mediaKeys and the mediaKeys attribute are the same object, return
2817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    a promise resolved with undefined.
2827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (thisElement.m_mediaKeys == mediaKeys)
2837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return ScriptPromise::cast(scriptState, V8ValueTraits<V8UndefinedType>::toV8Value(V8UndefinedType(), scriptState->context()->Global(), scriptState->isolate()));
2847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2. Let promise be a new promise. Remaining steps done in handler.
2867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return SetMediaKeysHandler::create(scriptState, element, mediaKeys);
287d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
289d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Create a MediaKeyNeededEvent for WD EME.
290a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatic PassRefPtrWillBeRawPtr<Event> createNeedKeyEvent(const String& contentType, const unsigned char* initData, unsigned initDataLength)
291d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
292d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    MediaKeyNeededEventInit initializer;
293d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.contentType = contentType;
294d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.initData = Uint8Array::create(initData, initDataLength);
295d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.bubbles = false;
296d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.cancelable = false;
297d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
298d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return MediaKeyNeededEvent::create(EventTypeNames::needkey, initializer);
299d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
300d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
301d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Create a 'needkey' MediaKeyEvent for v0.1b EME.
302a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatic PassRefPtrWillBeRawPtr<Event> createWebkitNeedKeyEvent(const String& contentType, const unsigned char* initData, unsigned initDataLength)
303d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
304d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    MediaKeyEventInit webkitInitializer;
305d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    webkitInitializer.keySystem = String();
306d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    webkitInitializer.sessionId = String();
307d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    webkitInitializer.initData = Uint8Array::create(initData, initDataLength);
308d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    webkitInitializer.bubbles = false;
309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    webkitInitializer.cancelable = false;
310d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
311d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return MediaKeyEvent::create(EventTypeNames::webkitneedkey, webkitInitializer);
312d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
313d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
314d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& element, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState& exceptionState)
315d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
316d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HTMLMediaElementEncryptedMedia::from(element).generateKeyRequest(element.webMediaPlayer(), keySystem, initData, exceptionState);
317d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
318d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
319e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void HTMLMediaElementEncryptedMedia::generateKeyRequest(WebMediaPlayer* webMediaPlayer, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState& exceptionState)
320d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
321d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest");
322d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
3237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!setEmeMode(EmeModePrefixed)) {
3247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        exceptionState.throwDOMException(InvalidStateError, "Mixed use of EME prefixed and unprefixed API not allowed.");
325d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
3267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
327d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
328d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (keySystem.isEmpty()) {
329d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(SyntaxError, "The key system provided is empty.");
330d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
331d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
332d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
333d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!webMediaPlayer) {
334d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "No media has been loaded.");
335d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
336d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
337d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
338d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const unsigned char* initDataPointer = 0;
339d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    unsigned initDataLength = 0;
340d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (initData) {
341d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        initDataPointer = initData->data();
342d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        initDataLength = initData->length();
343d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
344d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
345e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    WebMediaPlayer::MediaKeyException result = webMediaPlayer->generateKeyRequest(keySystem, initDataPointer, initDataLength);
346d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    throwExceptionIfMediaKeyExceptionOccurred(keySystem, String(), result, exceptionState);
347d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
348d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
349d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& mediaElement, const String& keySystem, ExceptionState& exceptionState)
350d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
351d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    webkitGenerateKeyRequest(mediaElement, keySystem, Uint8Array::create(0), exceptionState);
352d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
353d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
354d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& element, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState& exceptionState)
355d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
356d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HTMLMediaElementEncryptedMedia::from(element).addKey(element.webMediaPlayer(), keySystem, key, initData, sessionId, exceptionState);
357d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
358d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
359e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void HTMLMediaElementEncryptedMedia::addKey(WebMediaPlayer* webMediaPlayer, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState& exceptionState)
360d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
361d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitAddKey");
362d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
3637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!setEmeMode(EmeModePrefixed)) {
3647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        exceptionState.throwDOMException(InvalidStateError, "Mixed use of EME prefixed and unprefixed API not allowed.");
365d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
3667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
367d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
368d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (keySystem.isEmpty()) {
369d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(SyntaxError, "The key system provided is empty.");
370d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
371d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
372d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
373d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!key) {
374d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(SyntaxError, "The key provided is invalid.");
375d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
376d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
377d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
378d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!key->length()) {
379d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(TypeMismatchError, "The key provided is invalid.");
380d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
381d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
382d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
383d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!webMediaPlayer) {
384d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "No media has been loaded.");
385d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
386d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
387d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
388d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const unsigned char* initDataPointer = 0;
389d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    unsigned initDataLength = 0;
390d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (initData) {
391d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        initDataPointer = initData->data();
392d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        initDataLength = initData->length();
393d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
394d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
395e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    WebMediaPlayer::MediaKeyException result = webMediaPlayer->addKey(keySystem, key->data(), key->length(), initDataPointer, initDataLength, sessionId);
396d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    throwExceptionIfMediaKeyExceptionOccurred(keySystem, sessionId, result, exceptionState);
397d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
398d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
399d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& mediaElement, const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState& exceptionState)
400d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
401d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    webkitAddKey(mediaElement, keySystem, key, Uint8Array::create(0), String(), exceptionState);
402d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
403d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
404d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest(HTMLMediaElement& element, const String& keySystem, const String& sessionId, ExceptionState& exceptionState)
405d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
406d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HTMLMediaElementEncryptedMedia::from(element).cancelKeyRequest(element.webMediaPlayer(), keySystem, sessionId, exceptionState);
407d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
408d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
409e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void HTMLMediaElementEncryptedMedia::cancelKeyRequest(WebMediaPlayer* webMediaPlayer, const String& keySystem, const String& sessionId, ExceptionState& exceptionState)
410d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
411d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest");
412d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
4137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!setEmeMode(EmeModePrefixed)) {
4147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        exceptionState.throwDOMException(InvalidStateError, "Mixed use of EME prefixed and unprefixed API not allowed.");
415d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
4167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
417d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
418d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (keySystem.isEmpty()) {
419d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(SyntaxError, "The key system provided is empty.");
420d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
421d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
422d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
423d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!webMediaPlayer) {
424d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "No media has been loaded.");
425d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
426d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
427d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
428e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    WebMediaPlayer::MediaKeyException result = webMediaPlayer->cancelKeyRequest(keySystem, sessionId);
429d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    throwExceptionIfMediaKeyExceptionOccurred(keySystem, sessionId, result, exceptionState);
430d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
431d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
432d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::keyAdded(HTMLMediaElement& element, const String& keySystem, const String& sessionId)
433d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
434d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyAdded");
435d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
436d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    MediaKeyEventInit initializer;
437d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.keySystem = keySystem;
438d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.sessionId = sessionId;
439d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.bubbles = false;
440d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.cancelable = false;
441d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
442a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyadded, initializer);
443d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    event->setTarget(&element);
444d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    element.scheduleEvent(event.release());
445d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
446d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
447e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void HTMLMediaElementEncryptedMedia::keyError(HTMLMediaElement& element, const String& keySystem, const String& sessionId, WebMediaPlayerClient::MediaKeyErrorCode errorCode, unsigned short systemCode)
448d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
449d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyError: sessionID=%s, errorCode=%d, systemCode=%d", sessionId.utf8().data(), errorCode, systemCode);
450d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
451d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
452d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    switch (errorCode) {
453e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayerClient::MediaKeyErrorCodeUnknown:
454d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
455d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        break;
456e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayerClient::MediaKeyErrorCodeClient:
457d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
458d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        break;
459e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayerClient::MediaKeyErrorCodeService:
460d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_SERVICE;
461d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        break;
462e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayerClient::MediaKeyErrorCodeOutput:
463d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_OUTPUT;
464d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        break;
465e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayerClient::MediaKeyErrorCodeHardwareChange:
466d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_HARDWARECHANGE;
467d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        break;
468e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebMediaPlayerClient::MediaKeyErrorCodeDomain:
469d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_DOMAIN;
470d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        break;
471d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
472d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
473d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    MediaKeyEventInit initializer;
474d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.keySystem = keySystem;
475d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.sessionId = sessionId;
476d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.errorCode = MediaKeyError::create(mediaKeyErrorCode);
477d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.systemCode = systemCode;
478d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.bubbles = false;
479d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.cancelable = false;
480d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
481a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyerror, initializer);
482d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    event->setTarget(&element);
483d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    element.scheduleEvent(event.release());
484d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
485d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
486e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void HTMLMediaElementEncryptedMedia::keyMessage(HTMLMediaElement& element, const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const WebURL& defaultURL)
487d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
488d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyMessage: sessionID=%s", sessionId.utf8().data());
489d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
490d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    MediaKeyEventInit initializer;
491d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.keySystem = keySystem;
492d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.sessionId = sessionId;
493d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.message = Uint8Array::create(message, messageLength);
494d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.defaultURL = KURL(defaultURL);
495d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.bubbles = false;
496d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    initializer.cancelable = false;
497d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
498a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeymessage, initializer);
499d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    event->setTarget(&element);
500d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    element.scheduleEvent(event.release());
501d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
502d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
503d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::keyNeeded(HTMLMediaElement& element, const String& contentType, const unsigned char* initData, unsigned initDataLength)
504d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
505d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyNeeded: contentType=%s", contentType.utf8().data());
506d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
507d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (RuntimeEnabledFeatures::encryptedMediaEnabled()) {
508d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Send event for WD EME.
509a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        RefPtrWillBeRawPtr<Event> event = createNeedKeyEvent(contentType, initData, initDataLength);
510d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        event->setTarget(&element);
511d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        element.scheduleEvent(event.release());
512d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
513d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
514d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (RuntimeEnabledFeatures::prefixedEncryptedMediaEnabled()) {
515d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Send event for v0.1b EME.
516a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        RefPtrWillBeRawPtr<Event> event = createWebkitNeedKeyEvent(contentType, initData, initDataLength);
517d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        event->setTarget(&element);
518d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        element.scheduleEvent(event.release());
519d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
520d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
521d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
522d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void HTMLMediaElementEncryptedMedia::playerDestroyed(HTMLMediaElement& element)
523d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
524d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#if ENABLE(OILPAN)
525d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // FIXME: Oilpan: remove this once the media player is on the heap. crbug.com/378229
526d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (element.isFinalizing())
527d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return;
528d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif
529d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
530d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element);
5317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!thisElement.m_mediaKeys)
5327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
5337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(thisElement.m_emeMode == EmeModeUnprefixed);
5357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    thisElement.m_mediaKeys.clear();
536d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
537d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
538e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryptionModule(HTMLMediaElement& element)
539d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
540d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element);
541d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return thisElement.contentDecryptionModule();
542d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
543d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
544323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void HTMLMediaElementEncryptedMedia::trace(Visitor* visitor)
545323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
546323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    visitor->trace(m_mediaKeys);
547323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    WillBeHeapSupplement<HTMLMediaElement>::trace(visitor);
548323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
549323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
550c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
551