| 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/NavigatorRequestMediaKeySystemAccess.h" |
| 7 |
| 8 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 9 #include "bindings/core/v8/ScriptState.h" |
| 10 #include "core/dom/DOMException.h" |
| 11 #include "core/dom/ExceptionCode.h" |
| 12 #include "modules/encryptedmedia/MediaKeySystemAccess.h" |
| 13 #include "platform/ContentType.h" |
| 14 #include "platform/Logging.h" |
| 15 #include "platform/MIMETypeRegistry.h" |
| 16 #include "wtf/text/WTFString.h" |
| 17 |
| 18 namespace { |
| 19 |
| 20 static bool isKeySystemSupportedWithContentType(const String& keySystem, const S
tring& contentType) |
| 21 { |
| 22 ASSERT(!keySystem.isEmpty()); |
| 23 |
| 24 blink::ContentType type(contentType); |
| 25 String codecs = type.parameter("codecs"); |
| 26 return blink::MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem,
type.type(), codecs); |
| 27 } |
| 28 |
| 29 // This class allows capabilities to be checked and a MediaKeySystemAccess |
| 30 // object to be created asynchronously. |
| 31 class MediaKeySystemAccessInitializer final : public blink::ScriptPromiseResolve
r { |
| 32 WTF_MAKE_NONCOPYABLE(MediaKeySystemAccessInitializer); |
| 33 |
| 34 public: |
| 35 static blink::ScriptPromise create(blink::ScriptState*, const String& keySys
tem, const Vector<blink::MediaKeySystemOptions>& supportedConfigurations); |
| 36 virtual ~MediaKeySystemAccessInitializer(); |
| 37 |
| 38 private: |
| 39 MediaKeySystemAccessInitializer(blink::ScriptState*, const String& keySystem
, const Vector<blink::MediaKeySystemOptions>& supportedConfigurations); |
| 40 void timerFired(blink::Timer<MediaKeySystemAccessInitializer>*); |
| 41 |
| 42 const String m_keySystem; |
| 43 const Vector<blink::MediaKeySystemOptions> m_supportedConfigurations; |
| 44 blink::Timer<MediaKeySystemAccessInitializer> m_timer; |
| 45 }; |
| 46 |
| 47 blink::ScriptPromise MediaKeySystemAccessInitializer::create(blink::ScriptState*
scriptState, const String& keySystem, const Vector<blink::MediaKeySystemOptions
>& supportedConfigurations) |
| 48 { |
| 49 RefPtr<MediaKeySystemAccessInitializer> initializer = adoptRef(new MediaKeyS
ystemAccessInitializer(scriptState, keySystem, supportedConfigurations)); |
| 50 initializer->suspendIfNeeded(); |
| 51 initializer->keepAliveWhilePending(); |
| 52 return initializer->promise(); |
| 53 } |
| 54 |
| 55 MediaKeySystemAccessInitializer::MediaKeySystemAccessInitializer(blink::ScriptSt
ate* scriptState, const String& keySystem, const Vector<blink::MediaKeySystemOpt
ions>& supportedConfigurations) |
| 56 : blink::ScriptPromiseResolver(scriptState) |
| 57 , m_keySystem(keySystem) |
| 58 , m_supportedConfigurations(supportedConfigurations) |
| 59 , m_timer(this, &MediaKeySystemAccessInitializer::timerFired) |
| 60 { |
| 61 // Start the timer so that MediaKeySystemAccess can be created |
| 62 // asynchronously. |
| 63 // FIXME: If creating MediaKeySystemAccess or |
| 64 // isKeySystemSupportedWithContentType() is replaced with something |
| 65 // asynchronous, wait for the event rather than using a timer. |
| 66 m_timer.startOneShot(0, FROM_HERE); |
| 67 } |
| 68 |
| 69 MediaKeySystemAccessInitializer::~MediaKeySystemAccessInitializer() |
| 70 { |
| 71 } |
| 72 |
| 73 void MediaKeySystemAccessInitializer::timerFired(blink::Timer<MediaKeySystemAcce
ssInitializer>*) |
| 74 { |
| 75 // Continued from requestMediaKeySystemAccess(). |
| 76 // 5.1 If keySystem is not supported or not allowed in the origin of the |
| 77 // calling context's Document, return a promise rejected with a new |
| 78 // DOMException whose name is NotSupportedError. |
| 79 // (Handled by Chromium.) |
| 80 |
| 81 // 5.2 If supportedConfigurations was not provided, resolve the promise |
| 82 // with a new MediaKeySystemAccess object, execute the following steps: |
| 83 if (!m_supportedConfigurations.size()) { |
| 84 // 5.2.1 Let access be a new MediaKeySystemAccess object, and initialize |
| 85 // it as follows: |
| 86 // 5.2.1.1 Set the keySystem attribute to keySystem. |
| 87 blink::MediaKeySystemAccess* access = new blink::MediaKeySystemAccess(m_
keySystem); |
| 88 |
| 89 // 5.2.2 Resolve promise with access and abort these steps. |
| 90 resolve(access); |
| 91 return; |
| 92 } |
| 93 |
| 94 // 5.3 For each element of supportedConfigurations: |
| 95 // 5.3.1 Let combination be the element. |
| 96 // 5.3.2 For each dictionary member in combination: |
| 97 for (const auto& combination : m_supportedConfigurations) { |
| 98 // 5.3.2.1 If the member's value cannot be satisfied together in |
| 99 // combination with the previous members, continue to the next |
| 100 // iteration of the loop. |
| 101 // 5.3.3 If keySystem is supported and allowed in the origin of the |
| 102 // calling context's Document in the configuration specified by |
| 103 // the combination of the values in combination, execute the |
| 104 // following steps: |
| 105 // FIXME: This test needs to be enhanced to use more values from |
| 106 // combination. |
| 107 if (isKeySystemSupportedWithContentType(m_keySystem, combination.initDat
aType())) { |
| 108 // 5.3.3.1 Let access be a new MediaKeySystemAccess object, and |
| 109 // initialize it as follows: |
| 110 // 5.3.3.1.1 Set the keySystem attribute to keySystem. |
| 111 blink::MediaKeySystemAccess* access = new blink::MediaKeySystemAcces
s(m_keySystem); |
| 112 |
| 113 // 5.3.3.2 Resolve promise with access and abort these steps. |
| 114 resolve(access); |
| 115 return; |
| 116 } |
| 117 } |
| 118 |
| 119 // 5.4 Reject promise with a new DOMException whose name is |
| 120 // NotSupportedError. |
| 121 reject(blink::DOMException::create(blink::NotSupportedError, "There were no
supported combinations in supportedConfigurations.")); |
| 122 } |
| 123 |
| 124 } // namespace |
| 125 |
| 126 namespace blink { |
| 127 |
| 128 NavigatorRequestMediaKeySystemAccess::NavigatorRequestMediaKeySystemAccess() |
| 129 { |
| 130 } |
| 131 |
| 132 NavigatorRequestMediaKeySystemAccess::~NavigatorRequestMediaKeySystemAccess() |
| 133 { |
| 134 } |
| 135 |
| 136 NavigatorRequestMediaKeySystemAccess& NavigatorRequestMediaKeySystemAccess::from
(Navigator& navigator) |
| 137 { |
| 138 NavigatorRequestMediaKeySystemAccess* supplement = static_cast<NavigatorRequ
estMediaKeySystemAccess*>(WillBeHeapSupplement<Navigator>::from(navigator, suppl
ementName())); |
| 139 if (!supplement) { |
| 140 supplement = new NavigatorRequestMediaKeySystemAccess(); |
| 141 provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); |
| 142 } |
| 143 return *supplement; |
| 144 } |
| 145 |
| 146 ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( |
| 147 ScriptState* scriptState, |
| 148 Navigator& navigator, |
| 149 const String& keySystem) |
| 150 { |
| 151 // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/e
ncrypted-media.html#requestmediakeysystemaccess |
| 152 // When this method is invoked, the user agent must run the following steps: |
| 153 // 1. If keySystem is an empty string, return a promise rejected with a |
| 154 // new DOMException whose name is InvalidAccessError. |
| 155 if (keySystem.isEmpty()) { |
| 156 return ScriptPromise::rejectWithDOMException( |
| 157 scriptState, DOMException::create(InvalidAccessError, "The keySystem
parameter is empty.")); |
| 158 } |
| 159 |
| 160 // 2. If supportedConfigurations was provided and is empty, return a |
| 161 // promise rejected with a new DOMException whose name is |
| 162 // InvalidAccessError. |
| 163 // (no supportedConfigurations provided.) |
| 164 |
| 165 // Remainder of steps handled in common routine below. |
| 166 return NavigatorRequestMediaKeySystemAccess::from(navigator).requestMediaKey
SystemAccess(scriptState, keySystem, Vector<MediaKeySystemOptions>()); |
| 167 } |
| 168 |
| 169 ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( |
| 170 ScriptState* scriptState, |
| 171 Navigator& navigator, |
| 172 const String& keySystem, |
| 173 const Vector<MediaKeySystemOptions>& supportedConfigurations) |
| 174 { |
| 175 // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/e
ncrypted-media.html#requestmediakeysystemaccess |
| 176 // When this method is invoked, the user agent must run the following steps: |
| 177 // 1. If keySystem is an empty string, return a promise rejected with a |
| 178 // new DOMException whose name is InvalidAccessError. |
| 179 if (keySystem.isEmpty()) { |
| 180 return ScriptPromise::rejectWithDOMException( |
| 181 scriptState, DOMException::create(InvalidAccessError, "The keySystem
parameter is empty.")); |
| 182 } |
| 183 |
| 184 // 2. If supportedConfigurations was provided and is empty, return a |
| 185 // promise rejected with a new DOMException whose name is |
| 186 // InvalidAccessError. |
| 187 if (!supportedConfigurations.size()) { |
| 188 return ScriptPromise::rejectWithDOMException( |
| 189 scriptState, DOMException::create(InvalidAccessError, "The supported
Configurations parameter is empty.")); |
| 190 } |
| 191 |
| 192 // Remainder of steps handled in common routine below. |
| 193 return NavigatorRequestMediaKeySystemAccess::from(navigator).requestMediaKey
SystemAccess( |
| 194 scriptState, keySystem, supportedConfigurations); |
| 195 } |
| 196 |
| 197 ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( |
| 198 ScriptState* scriptState, |
| 199 const String& keySystem, |
| 200 const Vector<MediaKeySystemOptions>& supportedConfigurations) |
| 201 { |
| 202 // Continued from above. |
| 203 // 3. If keySystem is not one of the Key Systems supported by the user |
| 204 // agent, return a promise rejected with a new DOMException whose name |
| 205 // is NotSupportedError. String comparison is case-sensitive. |
| 206 if (!isKeySystemSupportedWithContentType(keySystem, "")) { |
| 207 return ScriptPromise::rejectWithDOMException( |
| 208 scriptState, DOMException::create(NotSupportedError, "The key system
specified is not supported.")); |
| 209 } |
| 210 |
| 211 // 4. Let promise be a new promise. |
| 212 // 5. Asynchronously determine support, and if allowed, create and |
| 213 // initialize the MediaKeySystemAccess object. |
| 214 // 6. Return promise. |
| 215 return MediaKeySystemAccessInitializer::create(scriptState, keySystem, suppo
rtedConfigurations); |
| 216 } |
| 217 |
| 218 const char* NavigatorRequestMediaKeySystemAccess::supplementName() |
| 219 { |
| 220 return "RequestMediaKeySystemAccess"; |
| 221 } |
| 222 |
| 223 void NavigatorRequestMediaKeySystemAccess::trace(Visitor* visitor) |
| 224 { |
| 225 WillBeHeapSupplement<Navigator>::trace(visitor); |
| 226 } |
| 227 |
| 228 } // namespace blink |
| OLD | NEW |