Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "config.h" | |
| 6 #include "modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h" | |
| 7 | |
| 8 #include "RuntimeEnabledFeatures.h" | |
| 9 #include "bindings/v8/ExceptionState.h" | |
| 10 #include "core/dom/ExceptionCode.h" | |
| 11 #include "core/html/HTMLMediaElement.h" | |
| 12 #include "core/html/MediaKeyError.h" | |
| 13 #include "core/html/MediaKeyEvent.h" | |
| 14 #include "modules/encryptedmedia/MediaKeyNeededEvent.h" | |
| 15 #include "modules/encryptedmedia/MediaKeys.h" | |
| 16 #include "platform/Logging.h" | |
| 17 | |
| 18 namespace WebCore { | |
| 19 | |
| 20 static void throwExceptionForMediaKeyException(const String& keySystem, const St ring& sessionId, blink::WebMediaPlayer::MediaKeyException exception, ExceptionSt ate& exceptionState) | |
| 21 { | |
| 22 switch (exception) { | |
| 23 case blink::WebMediaPlayer::MediaKeyExceptionNoError: | |
| 24 return; | |
| 25 case blink::WebMediaPlayer::MediaKeyExceptionInvalidPlayerState: | |
| 26 exceptionState.throwDOMException(InvalidStateError, "The player is in an invalid state."); | |
| 27 return; | |
| 28 case blink::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported: | |
| 29 exceptionState.throwDOMException(NotSupportedError, "The key system prov ided ('" + keySystem +"') is not supported."); | |
| 30 return; | |
| 31 case blink::WebMediaPlayer::MediaKeyExceptionInvalidAccess: | |
| 32 exceptionState.throwDOMException(InvalidAccessError, "The session ID pro vided ('" + sessionId + "') is invalid."); | |
| 33 return; | |
| 34 } | |
| 35 | |
| 36 ASSERT_NOT_REACHED(); | |
| 37 return; | |
| 38 } | |
| 39 | |
| 40 HTMLMediaElementEncryptedMedia::HTMLMediaElementEncryptedMedia(HTMLMediaElement& element) | |
| 41 : m_emeMode(EmeModeNotSelected) | |
| 42 , m_mediaElement(element) | |
|
acolwell GONE FROM CHROMIUM
2014/02/26 17:19:19
nit: I don't think you need this. In most cases, i
| |
| 43 { | |
| 44 } | |
| 45 | |
| 46 HTMLMediaElementEncryptedMedia::~HTMLMediaElementEncryptedMedia() | |
| 47 { | |
| 48 } | |
| 49 | |
| 50 const char* HTMLMediaElementEncryptedMedia::supplementName() | |
| 51 { | |
| 52 return "HTMLMediaElementEncryptedMedia"; | |
| 53 } | |
| 54 | |
| 55 HTMLMediaElementEncryptedMedia& HTMLMediaElementEncryptedMedia::from(HTMLMediaEl ement& element) | |
| 56 { | |
| 57 HTMLMediaElementEncryptedMedia* supplement = static_cast<HTMLMediaElementEnc ryptedMedia*>(Supplement<HTMLMediaElement>::from(element, supplementName())); | |
| 58 if (!supplement) { | |
| 59 supplement = new HTMLMediaElementEncryptedMedia(element); | |
| 60 provideTo(element, supplementName(), adoptPtr(supplement)); | |
| 61 } | |
| 62 return *supplement; | |
| 63 } | |
| 64 | |
| 65 bool HTMLMediaElementEncryptedMedia::setEmeMode(EmeMode emeMode, ExceptionState& exceptionState) | |
| 66 { | |
| 67 if (m_emeMode != EmeModeNotSelected && m_emeMode != emeMode) { | |
| 68 exceptionState.throwDOMException(InvalidStateError, "Mixed use of EME pr efixed and unprefixed API not allowed."); | |
| 69 return false; | |
| 70 } | |
| 71 m_emeMode = emeMode; | |
| 72 return true; | |
| 73 } | |
| 74 | |
| 75 blink::WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryp tionModule() | |
| 76 { | |
| 77 return m_mediaKeys ? m_mediaKeys->contentDecryptionModule() : 0; | |
| 78 } | |
| 79 | |
| 80 MediaKeys* HTMLMediaElementEncryptedMedia::mediaKeys(HTMLMediaElement& element) | |
| 81 { | |
| 82 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 83 return thisElement.m_mediaKeys.get(); | |
| 84 } | |
| 85 | |
| 86 void HTMLMediaElementEncryptedMedia::setMediaKeysInternal(MediaKeys* mediaKeys) | |
| 87 { | |
| 88 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::setMediaKeys"); | |
| 89 if (m_mediaKeys == mediaKeys) | |
| 90 return; | |
| 91 | |
| 92 ASSERT(m_emeMode = EmeModeUnprefixed); | |
| 93 | |
| 94 if (m_mediaKeys) | |
| 95 m_mediaKeys->setMediaElement(0); | |
| 96 m_mediaKeys = mediaKeys; | |
| 97 if (m_mediaKeys) | |
| 98 m_mediaKeys->setMediaElement(&m_mediaElement); | |
| 99 | |
| 100 // If a player is connected, tell it that the CDM has changed. | |
| 101 if (webMediaPlayer()) | |
| 102 webMediaPlayer()->setContentDecryptionModule(contentDecryptionModule()); | |
| 103 } | |
| 104 | |
| 105 void HTMLMediaElementEncryptedMedia::setMediaKeys(HTMLMediaElement& element, Med iaKeys* mediaKeys, ExceptionState& exceptionState) | |
| 106 { | |
| 107 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 108 | |
| 109 if (!thisElement.setEmeMode(EmeModeUnprefixed, exceptionState)) | |
| 110 return; | |
| 111 | |
| 112 thisElement.setMediaKeysInternal(mediaKeys); | |
| 113 } | |
| 114 | |
| 115 // Create a MediaKeyNeededEvent for WD EME. | |
| 116 static PassRefPtr<Event> createNeedKeyEvent(const String& contentType, const uns igned char* initData, unsigned initDataLength) | |
| 117 { | |
| 118 MediaKeyNeededEventInit initializer; | |
| 119 initializer.contentType = contentType; | |
| 120 initializer.initData = Uint8Array::create(initData, initDataLength); | |
| 121 initializer.bubbles = false; | |
| 122 initializer.cancelable = false; | |
| 123 | |
| 124 return MediaKeyNeededEvent::create(EventTypeNames::needkey, initializer); | |
| 125 } | |
| 126 | |
| 127 // Create a 'needkey' MediaKeyEvent for v0.1b EME. | |
| 128 static PassRefPtr<Event> createWebkitNeedKeyEvent(const String& contentType, con st unsigned char* initData, unsigned initDataLength) | |
| 129 { | |
| 130 MediaKeyEventInit webkitInitializer; | |
| 131 webkitInitializer.keySystem = String(); | |
| 132 webkitInitializer.sessionId = String(); | |
| 133 webkitInitializer.initData = Uint8Array::create(initData, initDataLength); | |
| 134 webkitInitializer.bubbles = false; | |
| 135 webkitInitializer.cancelable = false; | |
| 136 | |
| 137 return MediaKeyEvent::create(EventTypeNames::webkitneedkey, webkitInitialize r); | |
| 138 } | |
| 139 | |
| 140 void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& element, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionStat e& exceptionState) | |
| 141 { | |
| 142 HTMLMediaElementEncryptedMedia::from(element).generateKeyRequest(keySystem, initData, exceptionState); | |
| 143 } | |
| 144 | |
| 145 void HTMLMediaElementEncryptedMedia::generateKeyRequest(const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState& exceptionState) | |
| 146 { | |
| 147 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest"); | |
| 148 | |
| 149 if (!setEmeMode(EmeModePrefixed, exceptionState)) | |
| 150 return; | |
| 151 | |
| 152 if (keySystem.isEmpty()) { | |
| 153 exceptionState.throwDOMException(SyntaxError, "The key system provided i s empty."); | |
| 154 return; | |
| 155 } | |
| 156 | |
| 157 if (!m_mediaElement.player()) { | |
| 158 exceptionState.throwDOMException(InvalidStateError, "No media has been l oaded."); | |
| 159 return; | |
| 160 } | |
| 161 | |
| 162 const unsigned char* initDataPointer = 0; | |
| 163 unsigned initDataLength = 0; | |
| 164 if (initData) { | |
| 165 initDataPointer = initData->data(); | |
| 166 initDataLength = initData->length(); | |
| 167 } | |
| 168 | |
| 169 blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer() ? webMedi aPlayer()->generateKeyRequest(keySystem, initDataPointer, initDataLength) : blin k::WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | |
| 170 throwExceptionForMediaKeyException(keySystem, String(), result, exceptionSta te); | |
| 171 } | |
| 172 | |
| 173 void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& mediaElement, const String& keySystem, ExceptionState& exceptionState) | |
| 174 { | |
| 175 webkitGenerateKeyRequest(mediaElement, keySystem, Uint8Array::create(0), exc eptionState); | |
| 176 } | |
| 177 | |
| 178 void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& element, con st String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initDat a, const String& sessionId, ExceptionState& exceptionState) | |
| 179 { | |
| 180 HTMLMediaElementEncryptedMedia::from(element).addKey(keySystem, key, initDat a, sessionId, exceptionState); | |
| 181 } | |
| 182 | |
| 183 void HTMLMediaElementEncryptedMedia::addKey(const String& keySystem, PassRefPtr< Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, Excep tionState& exceptionState) | |
| 184 { | |
| 185 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitAddKey"); | |
| 186 | |
| 187 if (!setEmeMode(EmeModePrefixed, exceptionState)) | |
| 188 return; | |
| 189 | |
| 190 if (keySystem.isEmpty()) { | |
| 191 exceptionState.throwDOMException(SyntaxError, "The key system provided i s empty."); | |
| 192 return; | |
| 193 } | |
| 194 | |
| 195 if (!key) { | |
| 196 exceptionState.throwDOMException(SyntaxError, "The key provided is inval id."); | |
| 197 return; | |
| 198 } | |
| 199 | |
| 200 if (!key->length()) { | |
| 201 exceptionState.throwDOMException(TypeMismatchError, "The key provided is invalid."); | |
| 202 return; | |
| 203 } | |
| 204 | |
| 205 if (!m_mediaElement.player()) { | |
| 206 exceptionState.throwDOMException(InvalidStateError, "No media has been l oaded."); | |
| 207 return; | |
| 208 } | |
| 209 | |
| 210 const unsigned char* initDataPointer = 0; | |
| 211 unsigned initDataLength = 0; | |
| 212 if (initData) { | |
| 213 initDataPointer = initData->data(); | |
| 214 initDataLength = initData->length(); | |
| 215 } | |
| 216 | |
| 217 blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer() ? webMedi aPlayer()->addKey(keySystem, key->data(), key->length(), initDataPointer, initDa taLength, sessionId) : blink::WebMediaPlayer::MediaKeyExceptionInvalidPlayerStat e; | |
| 218 throwExceptionForMediaKeyException(keySystem, sessionId, result, exceptionSt ate); | |
| 219 } | |
| 220 | |
| 221 void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& mediaElement , const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState& exception State) | |
| 222 { | |
| 223 webkitAddKey(mediaElement, keySystem, key, Uint8Array::create(0), String(), exceptionState); | |
| 224 } | |
| 225 | |
| 226 void HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest(HTMLMediaElement& el ement, const String& keySystem, const String& sessionId, ExceptionState& excepti onState) | |
| 227 { | |
| 228 HTMLMediaElementEncryptedMedia::from(element).cancelKeyRequest(keySystem, se ssionId, exceptionState); | |
| 229 } | |
| 230 | |
| 231 void HTMLMediaElementEncryptedMedia::cancelKeyRequest(const String& keySystem, c onst String& sessionId, ExceptionState& exceptionState) | |
| 232 { | |
| 233 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest"); | |
| 234 | |
| 235 if (!setEmeMode(EmeModePrefixed, exceptionState)) | |
| 236 return; | |
| 237 | |
| 238 if (keySystem.isEmpty()) { | |
| 239 exceptionState.throwDOMException(SyntaxError, "The key system provided i s empty."); | |
| 240 return; | |
| 241 } | |
| 242 | |
| 243 if (!m_mediaElement.player()) { | |
| 244 exceptionState.throwDOMException(InvalidStateError, "No media has been l oaded."); | |
| 245 return; | |
| 246 } | |
| 247 | |
| 248 blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer() ? webMedi aPlayer()->cancelKeyRequest(keySystem, sessionId) : blink::WebMediaPlayer::Media KeyExceptionInvalidPlayerState; | |
| 249 throwExceptionForMediaKeyException(keySystem, sessionId, result, exceptionSt ate); | |
| 250 } | |
| 251 | |
| 252 void HTMLMediaElementEncryptedMedia::keyAdded(HTMLMediaElement& element, const b link::WebString& keySystem, const blink::WebString& sessionId) | |
| 253 { | |
| 254 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyAdded"); | |
| 255 | |
| 256 MediaKeyEventInit initializer; | |
| 257 initializer.keySystem = keySystem; | |
| 258 initializer.sessionId = sessionId; | |
| 259 initializer.bubbles = false; | |
| 260 initializer.cancelable = false; | |
| 261 | |
| 262 RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyadded, initializer); | |
| 263 event->setTarget(&element); | |
| 264 element.scheduleEvent(event.release()); | |
| 265 } | |
| 266 | |
| 267 void HTMLMediaElementEncryptedMedia::keyError(HTMLMediaElement& element, const b link::WebString& keySystem, const blink::WebString& sessionId, blink::WebMediaPl ayerClient::MediaKeyErrorCode errorCode, unsigned short systemCode) | |
| 268 { | |
| 269 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyError: session ID=%s, errorCode=%d, systemCode=%d", sessionId.utf8().data(), errorCode, systemC ode); | |
| 270 | |
| 271 MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; | |
| 272 switch (errorCode) { | |
| 273 case blink::WebMediaPlayerClient::MediaKeyErrorCodeUnknown: | |
| 274 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; | |
| 275 break; | |
| 276 case blink::WebMediaPlayerClient::MediaKeyErrorCodeClient: | |
| 277 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT; | |
| 278 break; | |
| 279 case blink::WebMediaPlayerClient::MediaKeyErrorCodeService: | |
| 280 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_SERVICE; | |
| 281 break; | |
| 282 case blink::WebMediaPlayerClient::MediaKeyErrorCodeOutput: | |
| 283 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_OUTPUT; | |
| 284 break; | |
| 285 case blink::WebMediaPlayerClient::MediaKeyErrorCodeHardwareChange: | |
| 286 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_HARDWARECHANGE; | |
| 287 break; | |
| 288 case blink::WebMediaPlayerClient::MediaKeyErrorCodeDomain: | |
| 289 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_DOMAIN; | |
| 290 break; | |
| 291 } | |
| 292 | |
| 293 MediaKeyEventInit initializer; | |
| 294 initializer.keySystem = keySystem; | |
| 295 initializer.sessionId = sessionId; | |
| 296 initializer.errorCode = MediaKeyError::create(mediaKeyErrorCode); | |
| 297 initializer.systemCode = systemCode; | |
| 298 initializer.bubbles = false; | |
| 299 initializer.cancelable = false; | |
| 300 | |
| 301 RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyerror, initializer); | |
| 302 event->setTarget(&element); | |
| 303 element.scheduleEvent(event.release()); | |
| 304 } | |
| 305 | |
| 306 void HTMLMediaElementEncryptedMedia::keyMessage(HTMLMediaElement& element, const blink::WebString& keySystem, const blink::WebString& sessionId, const unsigned char* message, unsigned messageLength, const blink::WebURL& defaultURL) | |
| 307 { | |
| 308 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyMessage: sessi onID=%s", sessionId.utf8().data()); | |
| 309 | |
| 310 MediaKeyEventInit initializer; | |
| 311 initializer.keySystem = keySystem; | |
| 312 initializer.sessionId = sessionId; | |
| 313 initializer.message = Uint8Array::create(message, messageLength); | |
| 314 initializer.defaultURL = KURL(defaultURL); | |
| 315 initializer.bubbles = false; | |
| 316 initializer.cancelable = false; | |
| 317 | |
| 318 RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeymessage , initializer); | |
| 319 event->setTarget(&element); | |
| 320 element.scheduleEvent(event.release()); | |
| 321 } | |
| 322 | |
| 323 void HTMLMediaElementEncryptedMedia::keyNeeded(HTMLMediaElement& element, const blink::WebString& contentType, const unsigned char* initData, unsigned initDataL ength) | |
| 324 { | |
| 325 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyNeeded: conten tType=%s", contentType.utf8().data()); | |
| 326 | |
| 327 if (RuntimeEnabledFeatures::encryptedMediaEnabled()) { | |
| 328 // Send event for WD EME. | |
| 329 RefPtr<Event> event = createNeedKeyEvent(contentType, initData, initData Length); | |
| 330 event->setTarget(&element); | |
| 331 element.scheduleEvent(event.release()); | |
| 332 } | |
| 333 | |
| 334 if (RuntimeEnabledFeatures::prefixedEncryptedMediaEnabled()) { | |
| 335 // Send event for v0.1b EME. | |
| 336 RefPtr<Event> event = createWebkitNeedKeyEvent(contentType, initData, in itDataLength); | |
| 337 event->setTarget(&element); | |
| 338 element.scheduleEvent(event.release()); | |
| 339 } | |
| 340 } | |
| 341 | |
| 342 void HTMLMediaElementEncryptedMedia::playerDestroyed(HTMLMediaElement& element) | |
| 343 { | |
| 344 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 345 thisElement.setMediaKeysInternal(0); | |
| 346 } | |
| 347 | |
| 348 blink::WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryp tionModule(HTMLMediaElement& element) | |
| 349 { | |
| 350 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 351 return thisElement.contentDecryptionModule(); | |
| 352 } | |
| 353 | |
| 354 blink::WebMediaPlayer* HTMLMediaElementEncryptedMedia::webMediaPlayer() | |
|
acolwell GONE FROM CHROMIUM
2014/02/26 17:19:19
nit: I think this should be on HTMLMediaElement in
| |
| 355 { | |
| 356 MediaPlayer* player = m_mediaElement.player(); | |
| 357 return player? player->webMediaPlayer() : 0; | |
| 358 } | |
| 359 | |
| 360 } // namespace WebCore | |
| OLD | NEW |