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