Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Apple Inc. All rights reserved. | 2 * Copyright (C) 2013 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 | 28 |
| 29 #include "bindings/core/v8/ScriptPromiseResolver.h" | 29 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 30 #include "bindings/core/v8/ScriptState.h" | 30 #include "bindings/core/v8/ScriptState.h" |
| 31 #include "core/dom/DOMException.h" | 31 #include "core/dom/DOMException.h" |
| 32 #include "core/dom/Document.h" | 32 #include "core/dom/Document.h" |
| 33 #include "core/dom/ExceptionCode.h" | 33 #include "core/dom/ExceptionCode.h" |
| 34 #include "core/dom/ExecutionContext.h" | 34 #include "core/dom/ExecutionContext.h" |
| 35 #include "modules/encryptedmedia/MediaKeyMessageEvent.h" | 35 #include "modules/encryptedmedia/MediaKeyMessageEvent.h" |
| 36 #include "modules/encryptedmedia/MediaKeySession.h" | 36 #include "modules/encryptedmedia/MediaKeySession.h" |
| 37 #include "modules/encryptedmedia/MediaKeysController.h" | 37 #include "modules/encryptedmedia/MediaKeysController.h" |
| 38 #include "modules/encryptedmedia/SimpleContentDecryptionModuleResult.h" | |
| 38 #include "platform/ContentType.h" | 39 #include "platform/ContentType.h" |
| 39 #include "platform/Logging.h" | 40 #include "platform/Logging.h" |
| 40 #include "platform/MIMETypeRegistry.h" | 41 #include "platform/MIMETypeRegistry.h" |
| 41 #include "platform/Timer.h" | 42 #include "platform/Timer.h" |
| 42 #include "platform/UUID.h" | 43 #include "platform/UUID.h" |
| 43 #include "public/platform/Platform.h" | 44 #include "public/platform/Platform.h" |
| 44 #include "public/platform/WebContentDecryptionModule.h" | 45 #include "public/platform/WebContentDecryptionModule.h" |
| 45 #include "wtf/ArrayBuffer.h" | 46 #include "wtf/ArrayBuffer.h" |
| 46 #include "wtf/ArrayBufferView.h" | 47 #include "wtf/ArrayBufferView.h" |
| 47 #include "wtf/RefPtr.h" | 48 #include "wtf/RefPtr.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 65 ContentType type(contentType); | 66 ContentType type(contentType); |
| 66 String codecs = type.parameter("codecs"); | 67 String codecs = type.parameter("codecs"); |
| 67 return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.t ype(), codecs); | 68 return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.t ype(), codecs); |
| 68 } | 69 } |
| 69 | 70 |
| 70 static ScriptPromise createRejectedPromise(ScriptState* scriptState, ExceptionCo de error, const String& errorMessage) | 71 static ScriptPromise createRejectedPromise(ScriptState* scriptState, ExceptionCo de error, const String& errorMessage) |
| 71 { | 72 { |
| 72 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea te(error, errorMessage)); | 73 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea te(error, errorMessage)); |
| 73 } | 74 } |
| 74 | 75 |
| 76 // A class holding a pending action. | |
| 77 class MediaKeys::PendingAction : public GarbageCollectedFinalized<MediaKeys::Pen dingAction> { | |
| 78 public: | |
| 79 const Persistent<ContentDecryptionModuleResult> result() const | |
| 80 { | |
| 81 return m_result; | |
| 82 } | |
| 83 | |
| 84 const RefPtr<ArrayBuffer> data() const | |
| 85 { | |
| 86 return m_data; | |
| 87 } | |
| 88 | |
| 89 static PendingAction* CreatePendingSetServerCertificate(ContentDecryptionMod uleResult* result, PassRefPtr<ArrayBuffer> serverCertificate) | |
| 90 { | |
| 91 ASSERT(result); | |
| 92 ASSERT(serverCertificate); | |
| 93 return new PendingAction(result, serverCertificate); | |
| 94 } | |
| 95 | |
| 96 ~PendingAction() | |
| 97 { | |
| 98 } | |
| 99 | |
| 100 void trace(Visitor* visitor) | |
| 101 { | |
| 102 visitor->trace(m_result); | |
| 103 } | |
| 104 | |
| 105 private: | |
| 106 PendingAction(ContentDecryptionModuleResult* result, PassRefPtr<ArrayBuffer> data) | |
| 107 : m_result(result) | |
| 108 , m_data(data) | |
| 109 { | |
| 110 } | |
| 111 | |
| 112 const Member<ContentDecryptionModuleResult> m_result; | |
| 113 const RefPtr<ArrayBuffer> m_data; | |
| 114 }; | |
| 115 | |
| 75 // This class allows a MediaKeys object to be created asynchronously. | 116 // This class allows a MediaKeys object to be created asynchronously. |
| 76 class MediaKeysInitializer : public ScriptPromiseResolver { | 117 class MediaKeysInitializer : public ScriptPromiseResolver { |
| 77 WTF_MAKE_NONCOPYABLE(MediaKeysInitializer); | 118 WTF_MAKE_NONCOPYABLE(MediaKeysInitializer); |
| 78 | 119 |
| 79 public: | 120 public: |
| 80 static ScriptPromise create(ScriptState*, const String& keySystem); | 121 static ScriptPromise create(ScriptState*, const String& keySystem); |
| 81 virtual ~MediaKeysInitializer(); | 122 virtual ~MediaKeysInitializer(); |
| 82 | 123 |
| 83 private: | 124 private: |
| 84 MediaKeysInitializer(ScriptState*, const String& keySystem); | 125 MediaKeysInitializer(ScriptState*, const String& keySystem); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 // 3. Let promise be a new promise. | 211 // 3. Let promise be a new promise. |
| 171 // 4. Asynchronously create and initialize the MediaKeys. | 212 // 4. Asynchronously create and initialize the MediaKeys. |
| 172 // 5. Return promise. | 213 // 5. Return promise. |
| 173 return MediaKeysInitializer::create(scriptState, keySystem); | 214 return MediaKeysInitializer::create(scriptState, keySystem); |
| 174 } | 215 } |
| 175 | 216 |
| 176 MediaKeys::MediaKeys(ExecutionContext* context, const String& keySystem, PassOwn Ptr<WebContentDecryptionModule> cdm) | 217 MediaKeys::MediaKeys(ExecutionContext* context, const String& keySystem, PassOwn Ptr<WebContentDecryptionModule> cdm) |
| 177 : ContextLifecycleObserver(context) | 218 : ContextLifecycleObserver(context) |
| 178 , m_keySystem(keySystem) | 219 , m_keySystem(keySystem) |
| 179 , m_cdm(cdm) | 220 , m_cdm(cdm) |
| 221 , m_timer(this, &MediaKeys::timerFired) | |
| 180 { | 222 { |
| 181 WTF_LOG(Media, "MediaKeys(%p)::MediaKeys", this); | 223 WTF_LOG(Media, "MediaKeys(%p)::MediaKeys", this); |
| 182 | 224 |
| 183 // Step 4.4 of MediaKeys::create(): | 225 // Step 4.4 of MediaKeys::create(): |
| 184 // 4.4.1 Set the keySystem attribute to keySystem. | 226 // 4.4.1 Set the keySystem attribute to keySystem. |
| 185 ASSERT(!m_keySystem.isEmpty()); | 227 ASSERT(!m_keySystem.isEmpty()); |
| 186 } | 228 } |
| 187 | 229 |
| 188 MediaKeys::~MediaKeys() | 230 MediaKeys::~MediaKeys() |
| 189 { | 231 { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 203 // FIXME: Check whether sessionType is actually supported by the CDM. | 245 // FIXME: Check whether sessionType is actually supported by the CDM. |
| 204 ASSERT(sessionType == kTemporary || sessionType == kPersistent); | 246 ASSERT(sessionType == kTemporary || sessionType == kPersistent); |
| 205 | 247 |
| 206 // 2. Let session be a new MediaKeySession object, and initialize it as | 248 // 2. Let session be a new MediaKeySession object, and initialize it as |
| 207 // follows: | 249 // follows: |
| 208 // (Initialization is performed in the constructor.) | 250 // (Initialization is performed in the constructor.) |
| 209 // 3. Return session. | 251 // 3. Return session. |
| 210 return MediaKeySession::create(scriptState, this, sessionType); | 252 return MediaKeySession::create(scriptState, this, sessionType); |
| 211 } | 253 } |
| 212 | 254 |
| 255 ScriptPromise MediaKeys::setServerCertificate(ScriptState* scriptState, ArrayBuf fer* serverCertificate) | |
| 256 { | |
| 257 RefPtr<ArrayBuffer> serverCertificateCopy = ArrayBuffer::create(serverCertif icate->data(), serverCertificate->byteLength()); | |
| 258 return setServerCertificateInternal(scriptState, serverCertificateCopy.relea se()); | |
| 259 } | |
| 260 | |
| 261 ScriptPromise MediaKeys::setServerCertificate(ScriptState* scriptState, ArrayBuf ferView* serverCertificate) | |
| 262 { | |
| 263 RefPtr<ArrayBuffer> serverCertificateCopy = ArrayBuffer::create(serverCertif icate->baseAddress(), serverCertificate->byteLength()); | |
| 264 return setServerCertificateInternal(scriptState, serverCertificateCopy.relea se()); | |
| 265 } | |
| 266 | |
| 267 ScriptPromise MediaKeys::setServerCertificateInternal(ScriptState* scriptState, PassRefPtr<ArrayBuffer> serverCertificate) | |
| 268 { | |
| 269 // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/e ncrypted-media.html#dom-setservercertificate: | |
| 270 // The setServerCertificate(serverCertificate) method provides a server | |
| 271 // certificate to be used to encrypt messages to the license server. | |
| 272 // It must run the following steps: | |
| 273 // 1. If serverCertificate is an empty array, return a promise rejected | |
| 274 // with a new DOMException whose name is "InvalidAccessError". | |
| 275 if (!serverCertificate->byteLength()) { | |
| 276 return ScriptPromise::rejectWithDOMException( | |
| 277 scriptState, DOMException::create(InvalidAccessError, "The serverCer tificate parameter is empty.")); | |
| 278 } | |
| 279 | |
| 280 // 2. If the keySystem does not support server certificates, return a | |
| 281 // promise rejected with a new DOMException whose name is | |
| 282 // "NotSupportedError". | |
| 283 // (Let the CDM decide whether to support this or not.) | |
| 284 | |
| 285 // 3. Let certificate be a copy of the contents of the serverCertificate | |
| 286 // parameter. | |
| 287 // (Done in caller.) | |
| 288 | |
| 289 // 4. Let promise be a new promise. | |
| 290 SimpleContentDecryptionModuleResult* result = new SimpleContentDecryptionMod uleResult(scriptState); | |
| 291 ScriptPromise promise = result->promise(); | |
| 292 | |
| 293 // 5. Run the following steps asynchronously (documented in timerFired()). | |
| 294 m_pendingActions.append(PendingAction::CreatePendingSetServerCertificate(res ult, serverCertificate)); | |
|
sandersd (OOO until July 31)
2014/09/11 23:37:13
If the Chromium promises implementation is correct
jrummell
2014/09/12 20:49:03
The problem is that ClearKey will resolve the prom
ddorwin
2014/09/15 23:10:56
As discussed, let's keep it simple, consistent wit
jrummell
2014/09/17 23:39:24
Acknowledged.
| |
| 295 if (!m_timer.isActive()) | |
| 296 m_timer.startOneShot(0, FROM_HERE); | |
| 297 | |
| 298 // 6. Return promise. | |
| 299 return promise; | |
| 300 } | |
| 301 | |
| 213 bool MediaKeys::isTypeSupported(const String& keySystem, const String& contentTy pe) | 302 bool MediaKeys::isTypeSupported(const String& keySystem, const String& contentTy pe) |
| 214 { | 303 { |
| 215 WTF_LOG(Media, "MediaKeys::isTypeSupported(%s, %s)", keySystem.ascii().data( ), contentType.ascii().data()); | 304 WTF_LOG(Media, "MediaKeys::isTypeSupported(%s, %s)", keySystem.ascii().data( ), contentType.ascii().data()); |
| 216 | 305 |
| 217 // 1. If keySystem is an empty string, return false and abort these steps. | 306 // 1. If keySystem is an empty string, return false and abort these steps. |
| 218 if (keySystem.isEmpty()) | 307 if (keySystem.isEmpty()) |
| 219 return false; | 308 return false; |
| 220 | 309 |
| 221 // 2. If keySystem contains an unrecognized or unsupported Key System, retur n false and abort | 310 // 2. If keySystem contains an unrecognized or unsupported Key System, retur n false and abort |
| 222 // these steps. Key system string comparison is case-sensitive. | 311 // these steps. Key system string comparison is case-sensitive. |
| 223 if (!isKeySystemSupportedWithContentType(keySystem, "")) | 312 if (!isKeySystemSupportedWithContentType(keySystem, "")) |
| 224 return false; | 313 return false; |
| 225 | 314 |
| 226 // 3. If contentType is an empty string, return true and abort these steps. | 315 // 3. If contentType is an empty string, return true and abort these steps. |
| 227 if (contentType.isEmpty()) | 316 if (contentType.isEmpty()) |
| 228 return true; | 317 return true; |
| 229 | 318 |
| 230 // 4. If the Key System specified by keySystem does not support decrypting t he container and/or | 319 // 4. If the Key System specified by keySystem does not support decrypting t he container and/or |
| 231 // codec specified by contentType, return false and abort these steps. | 320 // codec specified by contentType, return false and abort these steps. |
| 232 return isKeySystemSupportedWithContentType(keySystem, contentType); | 321 return isKeySystemSupportedWithContentType(keySystem, contentType); |
| 233 } | 322 } |
| 234 | 323 |
| 324 void MediaKeys::timerFired(Timer<MediaKeys>*) | |
| 325 { | |
| 326 ASSERT(m_pendingActions.size()); | |
| 327 | |
| 328 // Resolving promises now run synchronously and may result in additional | |
|
ddorwin
2014/09/15 23:10:56
"now"? I assume this was inspired by the change in
jrummell
2014/09/17 23:39:24
Comment removed.
| |
| 329 // actions getting added to the queue. As a result, swap the queue to | |
|
ddorwin
2014/09/15 23:10:56
nit: s/As a result,/Therefore,/
jrummell
2014/09/17 23:39:24
Changed.
| |
| 330 // a local copy to avoid problems if this happens. | |
| 331 HeapDeque<Member<PendingAction> > pendingActions; | |
| 332 pendingActions.swap(m_pendingActions); | |
| 333 | |
| 334 while (!pendingActions.isEmpty()) { | |
| 335 PendingAction* action = pendingActions.takeFirst(); | |
| 336 WTF_LOG(Media, "MediaKeys(%p)::timerFired: Certificate", this); | |
| 337 | |
| 338 // 5.1 Let cdm be the cdm during the initialization of this object. | |
| 339 WebContentDecryptionModule* cdm = contentDecryptionModule(); | |
| 340 | |
| 341 // 5.2 Use the cdm to process certificate. | |
| 342 cdm->setServerCertificate(static_cast<unsigned char*>(action->data()->da ta()), action->data()->byteLength(), action->result()->result()); | |
| 343 // 5.3 If any of the preceding steps failed, reject promise with a | |
| 344 // new DOMException whose name is the appropriate error name. | |
| 345 // 5.4 Resolve promise. | |
| 346 // These are handled by Chromium and the CDM. | |
|
ddorwin
2014/09/15 23:10:56
Add () as elsewhere?
jrummell
2014/09/17 23:39:24
Done.
| |
| 347 } | |
| 348 } | |
| 349 | |
| 235 WebContentDecryptionModule* MediaKeys::contentDecryptionModule() | 350 WebContentDecryptionModule* MediaKeys::contentDecryptionModule() |
| 236 { | 351 { |
| 237 return m_cdm.get(); | 352 return m_cdm.get(); |
| 238 } | 353 } |
| 239 | 354 |
| 240 void MediaKeys::trace(Visitor* visitor) | 355 void MediaKeys::trace(Visitor* visitor) |
| 241 { | 356 { |
| 357 visitor->trace(m_pendingActions); | |
| 242 } | 358 } |
| 243 | 359 |
| 244 void MediaKeys::contextDestroyed() | 360 void MediaKeys::contextDestroyed() |
| 245 { | 361 { |
| 246 ContextLifecycleObserver::contextDestroyed(); | 362 ContextLifecycleObserver::contextDestroyed(); |
| 247 | 363 |
| 248 // We don't need the CDM anymore. | 364 // We don't need the CDM anymore. |
| 249 m_cdm.clear(); | 365 m_cdm.clear(); |
| 250 } | 366 } |
| 251 | 367 |
| 252 } // namespace blink | 368 } // namespace blink |
| OLD | NEW |