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() | |
| 41 : m_emeMode(EmeModeNotSelected) | |
| 42 { | |
| 43 } | |
| 44 | |
| 45 HTMLMediaElementEncryptedMedia::~HTMLMediaElementEncryptedMedia() | |
| 46 { | |
| 47 } | |
| 48 | |
| 49 const char* HTMLMediaElementEncryptedMedia::supplementName() | |
| 50 { | |
| 51 return "HTMLMediaElementEncryptedMedia"; | |
| 52 } | |
| 53 | |
| 54 HTMLMediaElementEncryptedMedia& HTMLMediaElementEncryptedMedia::from(HTMLMediaEl ement& element) | |
| 55 { | |
| 56 Supplement<HTMLMediaElement>* supplement = Supplement<HTMLMediaElement>::fro m(element, supplementName()); | |
| 57 if (!supplement) { | |
| 58 supplement = new HTMLMediaElementEncryptedMedia(); | |
| 59 provideTo(element, supplementName(), adoptPtr(supplement)); | |
| 60 } | |
| 61 return *static_cast<HTMLMediaElementEncryptedMedia*>(supplement); | |
| 62 } | |
| 63 | |
| 64 bool HTMLMediaElementEncryptedMedia::setEmeMode(EmeMode emeMode, ExceptionState& exceptionState) | |
| 65 { | |
| 66 if (m_emeMode != EmeModeNotSelected && m_emeMode != emeMode) { | |
| 67 exceptionState.throwDOMException(InvalidStateError, "Mixed use of EME pr efixed and unprefixed API not allowed."); | |
| 68 return false; | |
| 69 } | |
| 70 m_emeMode = emeMode; | |
| 71 return true; | |
| 72 } | |
| 73 | |
| 74 blink::WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryp tionModule() | |
| 75 { | |
| 76 return m_mediaKeys ? m_mediaKeys->contentDecryptionModule() : 0; | |
| 77 } | |
| 78 | |
| 79 MediaKeys* HTMLMediaElementEncryptedMedia::mediaKeys(HTMLMediaElement& element) | |
| 80 { | |
| 81 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 82 return thisElement.m_mediaKeys.get(); | |
| 83 } | |
| 84 | |
| 85 void HTMLMediaElementEncryptedMedia::setMediaKeysInternal(HTMLMediaElement& elem ent, MediaKeys* mediaKeys) | |
| 86 { | |
| 87 if (m_mediaKeys == mediaKeys) | |
| 88 return; | |
| 89 | |
| 90 ASSERT(m_emeMode = EmeModeUnprefixed); | |
|
acolwell GONE FROM CHROMIUM
2014/03/06 01:31:53
nit: s/=/==/?
| |
| 91 | |
| 92 if (m_mediaKeys) | |
| 93 m_mediaKeys->setMediaElement(0); | |
| 94 m_mediaKeys = mediaKeys; | |
| 95 if (m_mediaKeys) | |
| 96 m_mediaKeys->setMediaElement(&element); | |
| 97 | |
| 98 // If a player is connected, tell it that the CDM has changed. | |
| 99 if (element.webMediaPlayer()) | |
| 100 element.webMediaPlayer()->setContentDecryptionModule(contentDecryptionMo dule()); | |
| 101 } | |
| 102 | |
| 103 void HTMLMediaElementEncryptedMedia::setMediaKeys(HTMLMediaElement& element, Med iaKeys* mediaKeys, ExceptionState& exceptionState) | |
| 104 { | |
| 105 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::setMediaKeys"); | |
| 106 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 107 | |
| 108 if (!thisElement.setEmeMode(EmeModeUnprefixed, exceptionState)) | |
| 109 return; | |
| 110 | |
| 111 thisElement.setMediaKeysInternal(element, mediaKeys); | |
| 112 } | |
| 113 | |
| 114 // Create a MediaKeyNeededEvent for WD EME. | |
| 115 static PassRefPtr<Event> createNeedKeyEvent(const String& contentType, const uns igned char* initData, unsigned initDataLength) | |
| 116 { | |
| 117 MediaKeyNeededEventInit initializer; | |
| 118 initializer.contentType = contentType; | |
| 119 initializer.initData = Uint8Array::create(initData, initDataLength); | |
| 120 initializer.bubbles = false; | |
| 121 initializer.cancelable = false; | |
| 122 | |
| 123 return MediaKeyNeededEvent::create(EventTypeNames::needkey, initializer); | |
| 124 } | |
| 125 | |
| 126 // Create a 'needkey' MediaKeyEvent for v0.1b EME. | |
| 127 static PassRefPtr<Event> createWebkitNeedKeyEvent(const String& contentType, con st unsigned char* initData, unsigned initDataLength) | |
| 128 { | |
| 129 MediaKeyEventInit webkitInitializer; | |
| 130 webkitInitializer.keySystem = String(); | |
| 131 webkitInitializer.sessionId = String(); | |
| 132 webkitInitializer.initData = Uint8Array::create(initData, initDataLength); | |
| 133 webkitInitializer.bubbles = false; | |
| 134 webkitInitializer.cancelable = false; | |
| 135 | |
| 136 return MediaKeyEvent::create(EventTypeNames::webkitneedkey, webkitInitialize r); | |
| 137 } | |
| 138 | |
| 139 void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& element, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionStat e& exceptionState) | |
| 140 { | |
| 141 HTMLMediaElementEncryptedMedia::from(element).generateKeyRequest(element.web MediaPlayer(), keySystem, initData, exceptionState); | |
| 142 } | |
| 143 | |
| 144 void HTMLMediaElementEncryptedMedia::generateKeyRequest(blink::WebMediaPlayer* w ebMediaPlayer, const String& keySystem, PassRefPtr<Uint8Array> initData, Excepti onState& exceptionState) | |
| 145 { | |
| 146 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest"); | |
| 147 | |
| 148 if (!setEmeMode(EmeModePrefixed, exceptionState)) | |
| 149 return; | |
| 150 | |
| 151 if (keySystem.isEmpty()) { | |
| 152 exceptionState.throwDOMException(SyntaxError, "The key system provided i s empty."); | |
| 153 return; | |
| 154 } | |
| 155 | |
| 156 if (!webMediaPlayer) { | |
| 157 exceptionState.throwDOMException(InvalidStateError, "No media has been l oaded."); | |
| 158 return; | |
| 159 } | |
| 160 | |
| 161 const unsigned char* initDataPointer = 0; | |
| 162 unsigned initDataLength = 0; | |
| 163 if (initData) { | |
| 164 initDataPointer = initData->data(); | |
| 165 initDataLength = initData->length(); | |
| 166 } | |
| 167 | |
| 168 blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer->generateKe yRequest(keySystem, initDataPointer, initDataLength); | |
| 169 throwExceptionForMediaKeyException(keySystem, String(), result, exceptionSta te); | |
| 170 } | |
| 171 | |
| 172 void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& mediaElement, const String& keySystem, ExceptionState& exceptionState) | |
| 173 { | |
| 174 webkitGenerateKeyRequest(mediaElement, keySystem, Uint8Array::create(0), exc eptionState); | |
| 175 } | |
| 176 | |
| 177 void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& element, con st String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initDat a, const String& sessionId, ExceptionState& exceptionState) | |
| 178 { | |
| 179 HTMLMediaElementEncryptedMedia::from(element).addKey(element.webMediaPlayer( ), keySystem, key, initData, sessionId, exceptionState); | |
| 180 } | |
| 181 | |
| 182 void HTMLMediaElementEncryptedMedia::addKey(blink::WebMediaPlayer* webMediaPlaye r, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> i nitData, const String& sessionId, ExceptionState& exceptionState) | |
| 183 { | |
| 184 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitAddKey"); | |
| 185 | |
| 186 if (!setEmeMode(EmeModePrefixed, exceptionState)) | |
| 187 return; | |
| 188 | |
| 189 if (keySystem.isEmpty()) { | |
| 190 exceptionState.throwDOMException(SyntaxError, "The key system provided i s empty."); | |
| 191 return; | |
| 192 } | |
| 193 | |
| 194 if (!key) { | |
| 195 exceptionState.throwDOMException(SyntaxError, "The key provided is inval id."); | |
| 196 return; | |
| 197 } | |
| 198 | |
| 199 if (!key->length()) { | |
| 200 exceptionState.throwDOMException(TypeMismatchError, "The key provided is invalid."); | |
| 201 return; | |
| 202 } | |
| 203 | |
| 204 if (!webMediaPlayer) { | |
| 205 exceptionState.throwDOMException(InvalidStateError, "No media has been l oaded."); | |
| 206 return; | |
| 207 } | |
| 208 | |
| 209 const unsigned char* initDataPointer = 0; | |
| 210 unsigned initDataLength = 0; | |
| 211 if (initData) { | |
| 212 initDataPointer = initData->data(); | |
| 213 initDataLength = initData->length(); | |
| 214 } | |
| 215 | |
| 216 blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer->addKey(key System, key->data(), key->length(), initDataPointer, initDataLength, sessionId); | |
| 217 throwExceptionForMediaKeyException(keySystem, sessionId, result, exceptionSt ate); | |
|
acolwell GONE FROM CHROMIUM
2014/03/06 01:31:53
nit: This is a little deceiving because the name i
ddorwin
2014/03/06 02:01:19
This was copied from the old code. Shall we keep t
| |
| 218 } | |
| 219 | |
| 220 void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& mediaElement , const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState& exception State) | |
| 221 { | |
| 222 webkitAddKey(mediaElement, keySystem, key, Uint8Array::create(0), String(), exceptionState); | |
| 223 } | |
| 224 | |
| 225 void HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest(HTMLMediaElement& el ement, const String& keySystem, const String& sessionId, ExceptionState& excepti onState) | |
| 226 { | |
| 227 HTMLMediaElementEncryptedMedia::from(element).cancelKeyRequest(element.webMe diaPlayer(), keySystem, sessionId, exceptionState); | |
| 228 } | |
| 229 | |
| 230 void HTMLMediaElementEncryptedMedia::cancelKeyRequest(blink::WebMediaPlayer* web MediaPlayer, const String& keySystem, const String& sessionId, ExceptionState& e xceptionState) | |
| 231 { | |
| 232 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest"); | |
| 233 | |
| 234 if (!setEmeMode(EmeModePrefixed, exceptionState)) | |
| 235 return; | |
| 236 | |
| 237 if (keySystem.isEmpty()) { | |
| 238 exceptionState.throwDOMException(SyntaxError, "The key system provided i s empty."); | |
| 239 return; | |
| 240 } | |
| 241 | |
| 242 if (!webMediaPlayer) { | |
| 243 exceptionState.throwDOMException(InvalidStateError, "No media has been l oaded."); | |
| 244 return; | |
| 245 } | |
| 246 | |
| 247 blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer->cancelKeyR equest(keySystem, sessionId); | |
| 248 throwExceptionForMediaKeyException(keySystem, sessionId, result, exceptionSt ate); | |
| 249 } | |
| 250 | |
| 251 void HTMLMediaElementEncryptedMedia::keyAdded(HTMLMediaElement& element, const S tring& keySystem, const String& sessionId) | |
| 252 { | |
| 253 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyAdded"); | |
| 254 | |
| 255 MediaKeyEventInit initializer; | |
| 256 initializer.keySystem = keySystem; | |
| 257 initializer.sessionId = sessionId; | |
| 258 initializer.bubbles = false; | |
| 259 initializer.cancelable = false; | |
| 260 | |
| 261 RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyadded, initializer); | |
| 262 event->setTarget(&element); | |
| 263 element.scheduleEvent(event.release()); | |
| 264 } | |
| 265 | |
| 266 void HTMLMediaElementEncryptedMedia::keyError(HTMLMediaElement& element, const S tring& keySystem, const String& sessionId, blink::WebMediaPlayerClient::MediaKey ErrorCode errorCode, unsigned short systemCode) | |
| 267 { | |
| 268 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyError: session ID=%s, errorCode=%d, systemCode=%d", sessionId.utf8().data(), errorCode, systemC ode); | |
| 269 | |
| 270 MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; | |
| 271 switch (errorCode) { | |
| 272 case blink::WebMediaPlayerClient::MediaKeyErrorCodeUnknown: | |
| 273 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; | |
| 274 break; | |
| 275 case blink::WebMediaPlayerClient::MediaKeyErrorCodeClient: | |
| 276 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT; | |
| 277 break; | |
| 278 case blink::WebMediaPlayerClient::MediaKeyErrorCodeService: | |
| 279 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_SERVICE; | |
| 280 break; | |
| 281 case blink::WebMediaPlayerClient::MediaKeyErrorCodeOutput: | |
| 282 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_OUTPUT; | |
| 283 break; | |
| 284 case blink::WebMediaPlayerClient::MediaKeyErrorCodeHardwareChange: | |
| 285 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_HARDWARECHANGE; | |
| 286 break; | |
| 287 case blink::WebMediaPlayerClient::MediaKeyErrorCodeDomain: | |
| 288 mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_DOMAIN; | |
| 289 break; | |
| 290 } | |
| 291 | |
| 292 MediaKeyEventInit initializer; | |
| 293 initializer.keySystem = keySystem; | |
| 294 initializer.sessionId = sessionId; | |
| 295 initializer.errorCode = MediaKeyError::create(mediaKeyErrorCode); | |
| 296 initializer.systemCode = systemCode; | |
| 297 initializer.bubbles = false; | |
| 298 initializer.cancelable = false; | |
| 299 | |
| 300 RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyerror, initializer); | |
| 301 event->setTarget(&element); | |
| 302 element.scheduleEvent(event.release()); | |
| 303 } | |
| 304 | |
| 305 void HTMLMediaElementEncryptedMedia::keyMessage(HTMLMediaElement& element, const String& keySystem, const String& sessionId, const unsigned char* message, unsig ned messageLength, const blink::WebURL& defaultURL) | |
| 306 { | |
| 307 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyMessage: sessi onID=%s", sessionId.utf8().data()); | |
| 308 | |
| 309 MediaKeyEventInit initializer; | |
| 310 initializer.keySystem = keySystem; | |
| 311 initializer.sessionId = sessionId; | |
| 312 initializer.message = Uint8Array::create(message, messageLength); | |
| 313 initializer.defaultURL = KURL(defaultURL); | |
| 314 initializer.bubbles = false; | |
| 315 initializer.cancelable = false; | |
| 316 | |
| 317 RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeymessage , initializer); | |
| 318 event->setTarget(&element); | |
| 319 element.scheduleEvent(event.release()); | |
| 320 } | |
| 321 | |
| 322 void HTMLMediaElementEncryptedMedia::keyNeeded(HTMLMediaElement& element, const String& contentType, const unsigned char* initData, unsigned initDataLength) | |
| 323 { | |
| 324 WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyNeeded: conten tType=%s", contentType.utf8().data()); | |
| 325 | |
| 326 if (RuntimeEnabledFeatures::encryptedMediaEnabled()) { | |
| 327 // Send event for WD EME. | |
| 328 RefPtr<Event> event = createNeedKeyEvent(contentType, initData, initData Length); | |
| 329 event->setTarget(&element); | |
| 330 element.scheduleEvent(event.release()); | |
| 331 } | |
| 332 | |
| 333 if (RuntimeEnabledFeatures::prefixedEncryptedMediaEnabled()) { | |
| 334 // Send event for v0.1b EME. | |
| 335 RefPtr<Event> event = createWebkitNeedKeyEvent(contentType, initData, in itDataLength); | |
| 336 event->setTarget(&element); | |
| 337 element.scheduleEvent(event.release()); | |
| 338 } | |
| 339 } | |
| 340 | |
| 341 void HTMLMediaElementEncryptedMedia::playerDestroyed(HTMLMediaElement& element) | |
| 342 { | |
| 343 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 344 thisElement.setMediaKeysInternal(element, 0); | |
| 345 } | |
| 346 | |
| 347 blink::WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryp tionModule(HTMLMediaElement& element) | |
| 348 { | |
| 349 HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia ::from(element); | |
| 350 return thisElement.contentDecryptionModule(); | |
| 351 } | |
| 352 | |
| 353 } // namespace WebCore | |
| OLD | NEW |