| 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 |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| 23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "modules/encryptedmedia/MediaKeys.h" | 27 #include "modules/encryptedmedia/MediaKeys.h" |
| 28 | 28 |
| 29 #include "bindings/core/v8/ScriptPromiseResolver.h" | |
| 30 #include "bindings/core/v8/ScriptState.h" | 29 #include "bindings/core/v8/ScriptState.h" |
| 31 #include "core/dom/DOMArrayBuffer.h" | 30 #include "core/dom/DOMArrayBuffer.h" |
| 32 #include "core/dom/DOMArrayBufferView.h" | 31 #include "core/dom/DOMArrayBufferView.h" |
| 33 #include "core/dom/DOMException.h" | 32 #include "core/dom/DOMException.h" |
| 34 #include "core/dom/Document.h" | |
| 35 #include "core/dom/ExceptionCode.h" | 33 #include "core/dom/ExceptionCode.h" |
| 36 #include "core/dom/ExecutionContext.h" | 34 #include "core/dom/ExecutionContext.h" |
| 37 #include "modules/encryptedmedia/MediaKeyMessageEvent.h" | |
| 38 #include "modules/encryptedmedia/MediaKeySession.h" | 35 #include "modules/encryptedmedia/MediaKeySession.h" |
| 39 #include "modules/encryptedmedia/MediaKeysController.h" | |
| 40 #include "modules/encryptedmedia/SimpleContentDecryptionModuleResult.h" | 36 #include "modules/encryptedmedia/SimpleContentDecryptionModuleResult.h" |
| 41 #include "platform/ContentType.h" | 37 #include "platform/ContentType.h" |
| 42 #include "platform/Logging.h" | 38 #include "platform/Logging.h" |
| 43 #include "platform/MIMETypeRegistry.h" | 39 #include "platform/MIMETypeRegistry.h" |
| 44 #include "platform/Timer.h" | 40 #include "platform/Timer.h" |
| 45 #include "platform/UUID.h" | |
| 46 #include "public/platform/Platform.h" | |
| 47 #include "public/platform/WebContentDecryptionModule.h" | 41 #include "public/platform/WebContentDecryptionModule.h" |
| 48 #include "wtf/RefPtr.h" | 42 #include "wtf/RefPtr.h" |
| 49 | 43 |
| 50 namespace blink { | 44 namespace blink { |
| 51 | 45 |
| 52 static bool isKeySystemSupportedWithContentType(const String& keySystem, const S
tring& contentType) | 46 static bool isKeySystemSupportedWithContentType(const String& keySystem, const S
tring& contentType) |
| 53 { | 47 { |
| 54 ASSERT(!keySystem.isEmpty()); | 48 ASSERT(!keySystem.isEmpty()); |
| 55 | 49 |
| 56 ContentType type(contentType); | 50 ContentType type(contentType); |
| 57 String codecs = type.parameter("codecs"); | 51 String codecs = type.parameter("codecs"); |
| 58 return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.t
ype(), codecs); | 52 return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.t
ype(), codecs); |
| 59 } | 53 } |
| 60 | 54 |
| 61 static ScriptPromise createRejectedPromise(ScriptState* scriptState, ExceptionCo
de error, const String& errorMessage) | |
| 62 { | |
| 63 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea
te(error, errorMessage)); | |
| 64 } | |
| 65 | |
| 66 // A class holding a pending action. | 55 // A class holding a pending action. |
| 67 class MediaKeys::PendingAction : public GarbageCollectedFinalized<MediaKeys::Pen
dingAction> { | 56 class MediaKeys::PendingAction : public GarbageCollectedFinalized<MediaKeys::Pen
dingAction> { |
| 68 public: | 57 public: |
| 69 const Persistent<ContentDecryptionModuleResult> result() const | 58 const Persistent<ContentDecryptionModuleResult> result() const |
| 70 { | 59 { |
| 71 return m_result; | 60 return m_result; |
| 72 } | 61 } |
| 73 | 62 |
| 74 const RefPtr<ArrayBuffer> data() const | 63 const RefPtr<ArrayBuffer> data() const |
| 75 { | 64 { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 96 PendingAction(ContentDecryptionModuleResult* result, PassRefPtr<ArrayBuffer>
data) | 85 PendingAction(ContentDecryptionModuleResult* result, PassRefPtr<ArrayBuffer>
data) |
| 97 : m_result(result) | 86 : m_result(result) |
| 98 , m_data(data) | 87 , m_data(data) |
| 99 { | 88 { |
| 100 } | 89 } |
| 101 | 90 |
| 102 const Member<ContentDecryptionModuleResult> m_result; | 91 const Member<ContentDecryptionModuleResult> m_result; |
| 103 const RefPtr<ArrayBuffer> m_data; | 92 const RefPtr<ArrayBuffer> m_data; |
| 104 }; | 93 }; |
| 105 | 94 |
| 106 // This class allows a MediaKeys object to be created asynchronously. | |
| 107 class MediaKeysInitializer : public ScriptPromiseResolver { | |
| 108 WTF_MAKE_NONCOPYABLE(MediaKeysInitializer); | |
| 109 | |
| 110 public: | |
| 111 static ScriptPromise create(ScriptState*, const String& keySystem); | |
| 112 virtual ~MediaKeysInitializer(); | |
| 113 | |
| 114 private: | |
| 115 MediaKeysInitializer(ScriptState*, const String& keySystem); | |
| 116 void timerFired(Timer<MediaKeysInitializer>*); | |
| 117 | |
| 118 const String m_keySystem; | |
| 119 Timer<MediaKeysInitializer> m_timer; | |
| 120 }; | |
| 121 | |
| 122 ScriptPromise MediaKeysInitializer::create(ScriptState* scriptState, const Strin
g& keySystem) | |
| 123 { | |
| 124 RefPtr<MediaKeysInitializer> initializer = adoptRef(new MediaKeysInitializer
(scriptState, keySystem)); | |
| 125 initializer->suspendIfNeeded(); | |
| 126 initializer->keepAliveWhilePending(); | |
| 127 return initializer->promise(); | |
| 128 } | |
| 129 | |
| 130 MediaKeysInitializer::MediaKeysInitializer(ScriptState* scriptState, const Strin
g& keySystem) | |
| 131 : ScriptPromiseResolver(scriptState) | |
| 132 , m_keySystem(keySystem) | |
| 133 , m_timer(this, &MediaKeysInitializer::timerFired) | |
| 134 { | |
| 135 WTF_LOG(Media, "MediaKeysInitializer::MediaKeysInitializer"); | |
| 136 // Start the timer so that MediaKeys can be created asynchronously. | |
| 137 m_timer.startOneShot(0, FROM_HERE); | |
| 138 } | |
| 139 | |
| 140 MediaKeysInitializer::~MediaKeysInitializer() | |
| 141 { | |
| 142 WTF_LOG(Media, "MediaKeysInitializer::~MediaKeysInitializer"); | |
| 143 } | |
| 144 | |
| 145 void MediaKeysInitializer::timerFired(Timer<MediaKeysInitializer>*) | |
| 146 { | |
| 147 WTF_LOG(Media, "MediaKeysInitializer::timerFired"); | |
| 148 | |
| 149 // NOTE: Continued from step 4. of MediaKeys::create(). | |
| 150 // 4.1 Let cdm be the content decryption module corresponding to | |
| 151 // keySystem. | |
| 152 // 4.2 Load and initialize the cdm if necessary. | |
| 153 Document* document = toDocument(executionContext()); | |
| 154 MediaKeysController* controller = MediaKeysController::from(document->page()
); | |
| 155 // FIXME: make createContentDecryptionModule() asynchronous. | |
| 156 OwnPtr<WebContentDecryptionModule> cdm = controller->createContentDecryption
Module(executionContext(), m_keySystem); | |
| 157 | |
| 158 // 4.3 If cdm fails to load or initialize, reject promise with a new | |
| 159 // DOMException whose name is the appropriate error name and that | |
| 160 // has an appropriate message. | |
| 161 if (!cdm) { | |
| 162 String message("A content decryption module could not be loaded for the
'" + m_keySystem + "' key system."); | |
| 163 reject(DOMException::create(UnknownError, message)); | |
| 164 return; | |
| 165 } | |
| 166 | |
| 167 // 4.4 Let media keys be a new MediaKeys object. | |
| 168 MediaKeys* mediaKeys = new MediaKeys(executionContext(), m_keySystem, cdm.re
lease()); | |
| 169 | |
| 170 // 4.5. Resolve promise with media keys. | |
| 171 resolve(mediaKeys); | |
| 172 | |
| 173 // Note: As soon as the promise is resolved (or rejected), the | |
| 174 // ScriptPromiseResolver object (|this|) is freed. So access to | |
| 175 // any members will crash once the promise is fulfilled. | |
| 176 } | |
| 177 | |
| 178 ScriptPromise MediaKeys::create(ScriptState* scriptState, const String& keySyste
m) | |
| 179 { | |
| 180 WTF_LOG(Media, "MediaKeys::create(%s)", keySystem.ascii().data()); | |
| 181 | |
| 182 // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/e
ncrypted-media.html#dom-create: | |
| 183 // The create(keySystem) method creates a new MediaKeys object for keySystem
. It must run the following steps: | |
| 184 | |
| 185 // 1. If keySystem is an empty string, return a promise rejected with a new | |
| 186 // DOMException whose name is "InvalidAccessError" and that has the message | |
| 187 // "The keySystem parameter is empty." | |
| 188 if (keySystem.isEmpty()) { | |
| 189 return createRejectedPromise(scriptState, InvalidAccessError, "The keySy
stem parameter is empty."); | |
| 190 } | |
| 191 | |
| 192 // 2. If keySystem is not one of the Key Systems supported by the user | |
| 193 // agent, return a promise rejected with a new DOMException whose name is | |
| 194 // "NotSupportedError" and that has the message "The key system keySystem | |
| 195 // is not supported." String comparison is case-sensitive. | |
| 196 if (!isKeySystemSupportedWithContentType(keySystem, "")) { | |
| 197 // String message("The key system '" + keySystem + "' is not supported."
); | |
| 198 return createRejectedPromise(scriptState, NotSupportedError, "The key sy
stem '" + keySystem + "' is not supported."); | |
| 199 } | |
| 200 | |
| 201 // 3. Let promise be a new promise. | |
| 202 // 4. Asynchronously create and initialize the MediaKeys. | |
| 203 // 5. Return promise. | |
| 204 return MediaKeysInitializer::create(scriptState, keySystem); | |
| 205 } | |
| 206 | |
| 207 MediaKeys::MediaKeys(ExecutionContext* context, const String& keySystem, PassOwn
Ptr<WebContentDecryptionModule> cdm) | 95 MediaKeys::MediaKeys(ExecutionContext* context, const String& keySystem, PassOwn
Ptr<WebContentDecryptionModule> cdm) |
| 208 : ContextLifecycleObserver(context) | 96 : ContextLifecycleObserver(context) |
| 209 , m_keySystem(keySystem) | 97 , m_keySystem(keySystem) |
| 210 , m_cdm(cdm) | 98 , m_cdm(cdm) |
| 211 , m_timer(this, &MediaKeys::timerFired) | 99 , m_timer(this, &MediaKeys::timerFired) |
| 212 { | 100 { |
| 213 WTF_LOG(Media, "MediaKeys(%p)::MediaKeys", this); | 101 WTF_LOG(Media, "MediaKeys(%p)::MediaKeys", this); |
| 214 | 102 |
| 215 // Step 4.4 of MediaKeys::create(): | 103 // Step 4.4 of MediaKeys::create(): |
| 216 // 4.4.1 Set the keySystem attribute to keySystem. | 104 // 4.4.1 Set the keySystem attribute to keySystem. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 | 236 |
| 349 void MediaKeys::contextDestroyed() | 237 void MediaKeys::contextDestroyed() |
| 350 { | 238 { |
| 351 ContextLifecycleObserver::contextDestroyed(); | 239 ContextLifecycleObserver::contextDestroyed(); |
| 352 | 240 |
| 353 // We don't need the CDM anymore. | 241 // We don't need the CDM anymore. |
| 354 m_cdm.clear(); | 242 m_cdm.clear(); |
| 355 } | 243 } |
| 356 | 244 |
| 357 } // namespace blink | 245 } // namespace blink |
| OLD | NEW |