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 |