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(); | |
ddorwin
2014/03/01 01:08:48
Returning a reference to a value just created on t
c.shu
2014/03/02 15:35:06
The pointer is passed to provideTo() as a passOwnP
| |
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); | |
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.pla yer(), element.webMediaPlayer(), keySystem, initData, exceptionState); | |
142 } | |
143 | |
144 void HTMLMediaElementEncryptedMedia::generateKeyRequest(bool hasPlayer, blink::W ebMediaPlayer* webMediaPlayer, const String& keySystem, PassRefPtr<Uint8Array> i nitData, ExceptionState& 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 (!hasPlayer) { | |
ddorwin
2014/03/01 01:08:48
Reminder to myself: I still think we should get ri
| |
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 ? webMediaP layer->generateKeyRequest(keySystem, initDataPointer, initDataLength) : blink::W ebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | |
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.player(), eleme nt.webMediaPlayer(), keySystem, key, initData, sessionId, exceptionState); | |
180 } | |
181 | |
182 void HTMLMediaElementEncryptedMedia::addKey(bool hasPlayer, blink::WebMediaPlaye r* webMediaPlayer, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefP tr<Uint8Array> initData, 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 (!hasPlayer) { | |
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 ? webMediaP layer->addKey(keySystem, key->data(), key->length(), initDataPointer, initDataLe ngth, sessionId) : blink::WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | |
217 throwExceptionForMediaKeyException(keySystem, sessionId, result, exceptionSt ate); | |
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.playe r(), element.webMediaPlayer(), keySystem, sessionId, exceptionState); | |
228 } | |
229 | |
230 void HTMLMediaElementEncryptedMedia::cancelKeyRequest(bool hasPlayer, blink::Web MediaPlayer* webMediaPlayer, const String& keySystem, const String& sessionId, E xceptionState& exceptionState) | |
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 (!hasPlayer) { | |
243 exceptionState.throwDOMException(InvalidStateError, "No media has been l oaded."); | |
244 return; | |
245 } | |
246 | |
247 blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer ? webMediaP layer->cancelKeyRequest(keySystem, sessionId) : blink::WebMediaPlayer::MediaKeyE xceptionInvalidPlayerState; | |
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 |