Chromium Code Reviews| 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 blink { | |
| 19 | |
| 20 static bool isKeySystemSupportedWithContentType(const String& keySystem, const S tring& contentType) | |
| 21 { | |
| 22 ASSERT(!keySystem.isEmpty()); | |
| 23 | |
| 24 ContentType type(contentType); | |
| 25 String codecs = type.parameter("codecs"); | |
| 26 return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.t ype(), codecs); | |
| 27 } | |
| 28 | |
| 29 const char* mediaKeysRequirementValidValues[] = { "required", "optional", "disal lowed" }; | |
|
ddorwin
2014/10/23 18:02:31
Okay for now, I guess. We'll probably need to conv
jrummell
2014/10/23 22:13:15
Acknowledged.
| |
| 30 | |
| 31 static bool ValidMediaKeysRequirement(const String& itemValue) | |
|
ddorwin
2014/10/23 18:02:31
IsV...
jrummell
2014/10/23 22:13:16
Done.
| |
| 32 { | |
| 33 for (size_t i = 0; i < WTF_ARRAY_LENGTH(mediaKeysRequirementValidValues); ++ i) { | |
| 34 if (mediaKeysRequirementValidValues[i] == itemValue) | |
| 35 return true; | |
| 36 } | |
| 37 return false; | |
| 38 } | |
| 39 | |
| 40 MediaKeySystemOptions ConvertDictionaryIntoMediaKeySystemOptions(Dictionary& dic tionary, ExceptionState& exceptionState) | |
| 41 { | |
| 42 MediaKeySystemOptions result; | |
| 43 String itemValue; | |
| 44 | |
| 45 if (DictionaryHelper::get(dictionary, "initDataType", itemValue)) | |
| 46 result.setInitDataType(itemValue); | |
| 47 | |
| 48 if (DictionaryHelper::get(dictionary, "audioType", itemValue)) | |
| 49 result.setAudioType(itemValue); | |
| 50 | |
| 51 if (DictionaryHelper::get(dictionary, "audioCapability", itemValue)) | |
| 52 result.setAudioCapability(itemValue); | |
| 53 | |
| 54 if (DictionaryHelper::get(dictionary, "videoType", itemValue)) | |
| 55 result.setVideoType(itemValue); | |
| 56 | |
| 57 if (DictionaryHelper::get(dictionary, "videoCapability", itemValue)) | |
| 58 result.setVideoCapability(itemValue); | |
| 59 | |
| 60 if (DictionaryHelper::get(dictionary, "uniqueidentifier", itemValue)) { | |
| 61 if (!ValidMediaKeysRequirement(itemValue)) | |
| 62 exceptionState.throwTypeError("Invalid MediaKeysRequirement value fo r 'uniqueidentifier'."); | |
| 63 result.setUniqueidentifier(itemValue); | |
| 64 } | |
| 65 | |
| 66 if (DictionaryHelper::get(dictionary, "stateful", itemValue)) { | |
| 67 if (!ValidMediaKeysRequirement(itemValue)) | |
| 68 exceptionState.throwTypeError("Invalid MediaKeysRequirement value fo r 'stateful'."); | |
| 69 result.setStateful(itemValue); | |
| 70 } | |
| 71 | |
| 72 return result; | |
| 73 } | |
| 74 | |
| 75 // This class allows capabilities to be checked and a MediaKeySystemAccess | |
| 76 // object to be created asynchronously. | |
| 77 class MediaKeySystemAccessInitializer : public ScriptPromiseResolver { | |
| 78 WTF_MAKE_NONCOPYABLE(MediaKeySystemAccessInitializer); | |
| 79 | |
| 80 public: | |
| 81 static ScriptPromise create(ScriptState*, const String& keySystem, const Vec tor<MediaKeySystemOptions>& supportedConfigurations); | |
| 82 virtual ~MediaKeySystemAccessInitializer(); | |
| 83 | |
| 84 private: | |
| 85 MediaKeySystemAccessInitializer(ScriptState*, const String& keySystem, const Vector<MediaKeySystemOptions>& supportedConfigurations); | |
| 86 void timerFired(Timer<MediaKeySystemAccessInitializer>*); | |
| 87 | |
| 88 const String m_keySystem; | |
| 89 const Vector<MediaKeySystemOptions> m_supportedConfigurations; | |
| 90 Timer<MediaKeySystemAccessInitializer> m_timer; | |
| 91 }; | |
| 92 | |
| 93 ScriptPromise MediaKeySystemAccessInitializer::create(ScriptState* scriptState, const String& keySystem, const Vector<MediaKeySystemOptions>& supportedConfigura tions) | |
| 94 { | |
| 95 RefPtr<MediaKeySystemAccessInitializer> initializer = adoptRef(new MediaKeyS ystemAccessInitializer(scriptState, keySystem, supportedConfigurations)); | |
| 96 initializer->suspendIfNeeded(); | |
| 97 initializer->keepAliveWhilePending(); | |
| 98 return initializer->promise(); | |
| 99 } | |
| 100 | |
| 101 MediaKeySystemAccessInitializer::MediaKeySystemAccessInitializer(ScriptState* sc riptState, const String& keySystem, const Vector<MediaKeySystemOptions>& support edConfigurations) | |
| 102 : ScriptPromiseResolver(scriptState) | |
| 103 , m_keySystem(keySystem) | |
| 104 , m_supportedConfigurations(supportedConfigurations) | |
| 105 , m_timer(this, &MediaKeySystemAccessInitializer::timerFired) | |
| 106 { | |
| 107 WTF_LOG(Media, "MediaKeySystemAccessInitializer::MediaKeySystemAccessInitial izer"); | |
| 108 // Start the timer so that MediaKeySystemAccess can be created asynchronousl y. | |
| 109 m_timer.startOneShot(0, FROM_HERE); | |
| 110 } | |
| 111 | |
| 112 MediaKeySystemAccessInitializer::~MediaKeySystemAccessInitializer() | |
| 113 { | |
| 114 WTF_LOG(Media, "MediaKeySystemAccessInitializer::~MediaKeySystemAccessInitia lizer"); | |
| 115 } | |
| 116 | |
| 117 void MediaKeySystemAccessInitializer::timerFired(Timer<MediaKeySystemAccessIniti alizer>*) | |
| 118 { | |
| 119 WTF_LOG(Media, "MediaKeySystemAccessInitializer::timerFired"); | |
| 120 | |
| 121 // Continued from requestMediaKeySystemAccess(). | |
| 122 // 5.1 If keySystem is not supported or not allowed in the origin of the | |
| 123 // calling context's Document, return a promise rejected with a new | |
| 124 // DOMException whose name is NotSupportedError. | |
| 125 // (Handled by Chromium.) | |
| 126 | |
| 127 // 5.2 If supportedConfigurations was not provided, resolve the promise | |
| 128 // with a new MediaKeySystemAccess object, execute the following steps: | |
| 129 if (!m_supportedConfigurations.size()) { | |
| 130 // 5.2.1 Let access be a new MediaKeySystemAccess object, and initialize | |
| 131 // it as follows: | |
| 132 // 5.2.1.1 Set the keySystem attribute to keySystem. | |
| 133 MediaKeySystemAccess* access = new MediaKeySystemAccess(m_keySystem); | |
| 134 | |
| 135 // 5.2.2 Resolve promise with access and abort these steps. | |
| 136 resolve(access); | |
| 137 return; | |
| 138 } | |
| 139 | |
| 140 // 5.3 For each element of supportedConfigurations: | |
| 141 // 5.3.1 Let combination be the element. | |
| 142 // 5.3.2 For each dictionary member in combination: | |
| 143 for (const auto& combination : m_supportedConfigurations) { | |
| 144 // 5.3.2.1 If the member's value cannot be satisfied together in | |
| 145 // combination with the previous members, continue to the next | |
| 146 // iteration of the loop. | |
| 147 // 5.3.3 If keySystem is supported and allowed in the origin of the | |
| 148 // calling context's Document in the configuration specified by | |
| 149 // the combination of the values in combination, execute the | |
| 150 // following steps: | |
| 151 // FIXME: This test needs to be enhanced to use more values from | |
| 152 // combination. | |
| 153 if (isKeySystemSupportedWithContentType(m_keySystem, combination.initDat aType())) { | |
| 154 // 5.3.3.1 Let access be a new MediaKeySystemAccess object, and | |
| 155 // initialize it as follows: | |
| 156 // 5.3.3.1.1 Set the keySystem attribute to keySystem. | |
| 157 MediaKeySystemAccess* access = new MediaKeySystemAccess(m_keySystem) ; | |
| 158 | |
| 159 // 5.3.3.2 Resolve promise with access and abort these steps. | |
| 160 resolve(access); | |
| 161 return; | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 // 5.4 Reject promise with a new DOMException whose name is | |
| 166 // NotSupportedError. | |
| 167 reject(DOMException::create(NotSupportedError, "There were no supported comb inations in supportedConfigurations.")); | |
| 168 } | |
| 169 | |
| 170 NavigatorRequestMediaKeySystemAccess::NavigatorRequestMediaKeySystemAccess() | |
| 171 { | |
| 172 } | |
| 173 | |
| 174 NavigatorRequestMediaKeySystemAccess::~NavigatorRequestMediaKeySystemAccess() | |
| 175 { | |
| 176 } | |
| 177 | |
| 178 NavigatorRequestMediaKeySystemAccess& NavigatorRequestMediaKeySystemAccess::from (Navigator& navigator) | |
| 179 { | |
| 180 NavigatorRequestMediaKeySystemAccess* supplement = static_cast<NavigatorRequ estMediaKeySystemAccess*>(WillBeHeapSupplement<Navigator>::from(navigator, suppl ementName())); | |
| 181 if (!supplement) { | |
| 182 supplement = new NavigatorRequestMediaKeySystemAccess(); | |
| 183 provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); | |
| 184 } | |
| 185 return *supplement; | |
| 186 } | |
| 187 | |
| 188 ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( | |
| 189 ScriptState* scriptState, | |
| 190 Navigator& navigator, | |
| 191 const String& keySystem) | |
| 192 { | |
| 193 // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/e ncrypted-media.html#requestmediakeysystemaccess | |
| 194 // When this method is invoked, the user agent must run the following steps: | |
| 195 // 1. If keySystem is an empty string, return a promise rejected with a | |
| 196 // new DOMException whose name is InvalidAccessError. | |
| 197 if (keySystem.isEmpty()) { | |
| 198 return ScriptPromise::rejectWithDOMException( | |
| 199 scriptState, DOMException::create(InvalidAccessError, "The keySystem parameter is empty.")); | |
| 200 } | |
| 201 | |
| 202 // 2. If supportedConfigurations was provided and is empty, return a | |
| 203 // promise rejected with a new DOMException whose name is | |
| 204 // InvalidAccessError. | |
| 205 // (no supportedConfigurations provided.) | |
| 206 | |
| 207 // Remainder of steps handled in common routine below. | |
| 208 return NavigatorRequestMediaKeySystemAccess::from(navigator).requestMediaKey SystemAccess(scriptState, keySystem, Vector<MediaKeySystemOptions>()); | |
| 209 } | |
| 210 | |
| 211 ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( | |
| 212 ScriptState* scriptState, | |
| 213 Navigator& navigator, | |
| 214 const String& keySystem, | |
| 215 const Vector<MediaKeySystemOptions>& supportedConfigurations) | |
| 216 { | |
| 217 // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/e ncrypted-media.html#requestmediakeysystemaccess | |
| 218 // When this method is invoked, the user agent must run the following steps: | |
| 219 // 1. If keySystem is an empty string, return a promise rejected with a | |
| 220 // new DOMException whose name is InvalidAccessError. | |
| 221 if (keySystem.isEmpty()) { | |
| 222 return ScriptPromise::rejectWithDOMException( | |
| 223 scriptState, DOMException::create(InvalidAccessError, "The keySystem parameter is empty.")); | |
| 224 } | |
| 225 | |
| 226 // 2. If supportedConfigurations was provided and is empty, return a | |
| 227 // promise rejected with a new DOMException whose name is | |
| 228 // InvalidAccessError. | |
| 229 if (!supportedConfigurations.size()) { | |
| 230 return ScriptPromise::rejectWithDOMException( | |
| 231 scriptState, DOMException::create(InvalidAccessError, "The supported Configurations parameter is empty.")); | |
| 232 } | |
| 233 | |
| 234 // Remainder of steps handled in common routine below. | |
| 235 return NavigatorRequestMediaKeySystemAccess::from(navigator).requestMediaKey SystemAccess( | |
| 236 scriptState, keySystem, supportedConfigurations); | |
| 237 } | |
| 238 | |
| 239 ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( | |
| 240 ScriptState* scriptState, | |
| 241 const String& keySystem, | |
| 242 const Vector<MediaKeySystemOptions>& supportedConfigurations) | |
| 243 { | |
| 244 // Continued from above. | |
| 245 // 3. If keySystem is not one of the Key Systems supported by the user | |
| 246 // agent, return a promise rejected with a new DOMException whose name | |
| 247 // is NotSupportedError. String comparison is case-sensitive. | |
| 248 if (!isKeySystemSupportedWithContentType(keySystem, "")) { | |
| 249 return ScriptPromise::rejectWithDOMException( | |
| 250 scriptState, DOMException::create(NotSupportedError, "The key system specified is not supported.")); | |
| 251 } | |
| 252 | |
| 253 // 4. Let promise be a new promise. | |
| 254 // 5. Asynchronously determine support and if allowed create and | |
|
ddorwin
2014/10/23 18:02:31
nit: missing commas
jrummell
2014/10/23 22:13:15
Done.
| |
| 255 // initialize the MediaKeySystemAccess object. | |
| 256 // 6. Return promise. | |
| 257 return MediaKeySystemAccessInitializer::create(scriptState, keySystem, suppo rtedConfigurations); | |
| 258 } | |
| 259 | |
| 260 const char* NavigatorRequestMediaKeySystemAccess::supplementName() | |
| 261 { | |
| 262 return "RequestMediaKeySystemAccess"; | |
| 263 } | |
| 264 | |
| 265 void NavigatorRequestMediaKeySystemAccess::trace(Visitor* visitor) | |
| 266 { | |
| 267 WillBeHeapSupplement<Navigator>::trace(visitor); | |
| 268 } | |
| 269 | |
| 270 } // namespace blink | |
| OLD | NEW |