Chromium Code Reviews| Index: Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp |
| diff --git a/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp b/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..10c1a2c36b2f6a2c3a1bd6c2e735af23c4ecb200 |
| --- /dev/null |
| +++ b/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp |
| @@ -0,0 +1,221 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "config.h" |
| +#include "modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.h" |
| + |
| +#include "bindings/core/v8/ScriptPromiseResolver.h" |
| +#include "bindings/core/v8/ScriptState.h" |
| +#include "core/dom/DOMException.h" |
| +#include "core/dom/ExceptionCode.h" |
| +#include "modules/encryptedmedia/MediaKeySystemAccess.h" |
| +#include "platform/ContentType.h" |
| +#include "platform/Logging.h" |
| +#include "platform/MIMETypeRegistry.h" |
| + |
| +namespace blink { |
| + |
| +static bool isKeySystemSupportedWithContentType(const String& keySystem, const String& contentType) |
| +{ |
| + ASSERT(!keySystem.isEmpty()); |
| + |
| + ContentType type(contentType); |
| + String codecs = type.parameter("codecs"); |
| + return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.type(), codecs); |
| +} |
| + |
| +// This class allows a MediaKeySystemAccess object to be created asynchronously. |
|
ddorwin
2014/10/22 22:18:54
allows capabilities to be checked and... ?
jrummell
2014/10/23 01:20:03
Done.
|
| +class MediaKeySystemAccessInitializer : public ScriptPromiseResolver { |
|
ddorwin
2014/10/22 22:18:54
We should consider somehow avoiding the boilerplat
jrummell
2014/10/23 01:20:03
Acknowledged.
|
| + WTF_MAKE_NONCOPYABLE(MediaKeySystemAccessInitializer); |
| + |
| +public: |
| + static ScriptPromise create(ScriptState*, const String& keySystem, const Vector<MediaKeySystemOptions>& supportedConfigurations); |
| + virtual ~MediaKeySystemAccessInitializer(); |
| + |
| +private: |
| + MediaKeySystemAccessInitializer(ScriptState*, const String& keySystem, const Vector<MediaKeySystemOptions>& supportedConfigurations); |
| + void timerFired(Timer<MediaKeySystemAccessInitializer>*); |
| + |
| + const String m_keySystem; |
| + const Vector<MediaKeySystemOptions> m_supportedConfigurations; |
| + Timer<MediaKeySystemAccessInitializer> m_timer; |
| +}; |
| + |
| +ScriptPromise MediaKeySystemAccessInitializer::create(ScriptState* scriptState, const String& keySystem, const Vector<MediaKeySystemOptions>& supportedConfigurations) |
| +{ |
| + RefPtr<MediaKeySystemAccessInitializer> initializer = adoptRef(new MediaKeySystemAccessInitializer(scriptState, keySystem, supportedConfigurations)); |
| + initializer->suspendIfNeeded(); |
| + initializer->keepAliveWhilePending(); |
| + return initializer->promise(); |
| +} |
| + |
| +MediaKeySystemAccessInitializer::MediaKeySystemAccessInitializer(ScriptState* scriptState, const String& keySystem, const Vector<MediaKeySystemOptions>& supportedConfigurations) |
| + : ScriptPromiseResolver(scriptState) |
| + , m_keySystem(keySystem) |
| + , m_supportedConfigurations(supportedConfigurations) |
| + , m_timer(this, &MediaKeySystemAccessInitializer::timerFired) |
| +{ |
| + WTF_LOG(Media, "MediaKeySystemAccessInitializer::MediaKeySystemAccessInitializer"); |
| + // Start the timer so that MediaKeySystemAccess can be created asynchronously. |
| + m_timer.startOneShot(0, FROM_HERE); |
| +} |
| + |
| +MediaKeySystemAccessInitializer::~MediaKeySystemAccessInitializer() |
| +{ |
| + WTF_LOG(Media, "MediaKeySystemAccessInitializer::~MediaKeySystemAccessInitializer"); |
| +} |
| + |
| +void MediaKeySystemAccessInitializer::timerFired(Timer<MediaKeySystemAccessInitializer>*) |
| +{ |
| + WTF_LOG(Media, "MediaKeySystemAccessInitializer::timerFired"); |
| + |
| + // Continued from requestMediaKeySystemAccess(). |
| + // 5.1 If keySystem is not supported or not allowed in the origin of the |
| + // calling context's Document, return a promise rejected with a new |
| + // DOMException whose name is NotSupportedError. |
|
ddorwin
2014/10/22 22:18:54
(Handled by Chromium.)
jrummell
2014/10/23 01:20:03
Done.
|
| + |
| + // 5.2 If supportedConfigurations was not provided, resolve the promise |
| + // with a new MediaKeySystemAccess object, execute the following steps: |
| + if (!m_supportedConfigurations.size()) { |
| + // 5.2.1 Let access be a new MediaKeySystemAccess object, and initialize |
| + // it as follows: |
| + // 5.2.1.1 Set the keySystem attribute to keySystem. |
| + MediaKeySystemAccess* access = new MediaKeySystemAccess(m_keySystem); |
| + |
| + // 5.2.2 Resolve promise with access and abort these steps. |
| + resolve(access); |
| + return; |
| + } |
| + |
| + // 5.3 For each element of supportedConfigurations: |
| + // 5.3.1 Let combination be the element. |
| + // 5.3.2 For each dictionary member in combination: |
| + for (const auto& combination : m_supportedConfigurations) { |
| + // 5.3.2.1 If the member's value cannot be satisfied together in |
| + // combination with the previous members, continue to the next |
| + // iteration of the loop. |
| + // 5.3.3 If keySystem is supported and allowed in the origin of the |
| + // calling context's Document in the configuration specified by |
| + // the combination of the values in combination, execute the |
| + // following steps: |
| + // FIXME: This test needs to be enhanced to use more values from |
| + // combination. |
| + if (isKeySystemSupportedWithContentType(m_keySystem, combination.initDataType())) { |
| + // 5.3.3.1 Let access be a new MediaKeySystemAccess object, and |
| + // initialize it as follows: |
| + // 5.3.3.1.1 Set the keySystem attribute to keySystem. |
| + MediaKeySystemAccess* access = new MediaKeySystemAccess(m_keySystem); |
| + |
| + // 5.3.3.2 Resolve promise with access and abort these steps. |
| + resolve(access); |
| + return; |
| + } |
| + } |
| + |
| + // 5.4 Reject promise with a new DOMException whose name is |
| + // NotSupportedError. |
| + reject(DOMException::create(NotSupportedError, "There were no supported combinations in supportedConfigurations.")); |
| +} |
| + |
| +NavigatorRequestMediaKeySystemAccess::NavigatorRequestMediaKeySystemAccess() |
| +{ |
| +} |
| + |
| +NavigatorRequestMediaKeySystemAccess::~NavigatorRequestMediaKeySystemAccess() |
| +{ |
| +} |
| + |
| +NavigatorRequestMediaKeySystemAccess& NavigatorRequestMediaKeySystemAccess::from(Navigator& navigator) |
| +{ |
| + NavigatorRequestMediaKeySystemAccess* supplement = static_cast<NavigatorRequestMediaKeySystemAccess*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); |
| + if (!supplement) { |
| + supplement = new NavigatorRequestMediaKeySystemAccess(); |
| + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); |
| + } |
| + return *supplement; |
| +} |
| + |
| +ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( |
| + ScriptState* scriptState, |
| + Navigator& navigator, |
| + const String& keySystem) |
| +{ |
| + // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#requestmediakeysystemaccess |
| + // When this method is invoked, the user agent must run the following steps: |
| + // 1. If keySystem is an empty string, return a promise rejected with a |
| + // new DOMException whose name is InvalidAccessError. |
| + if (keySystem.isEmpty()) { |
| + return ScriptPromise::rejectWithDOMException( |
| + scriptState, DOMException::create(InvalidAccessError, "The keySystem parameter is empty.")); |
| + } |
| + |
| + // 2. If supportedConfigurations was provided and is empty, return a |
| + // promise rejected with a new DOMException whose name is |
| + // InvalidAccessError. |
| + // (no supportedConfigurations provided.) |
| + |
| + // Remainder of steps handled in common routine below. |
| + Vector<MediaKeySystemOptions> supportedConfigurations; |
|
ddorwin
2014/10/22 22:18:54
nit: Can you do this inline below?
jrummell
2014/10/23 01:20:03
Done.
|
| + return NavigatorRequestMediaKeySystemAccess::from(navigator).requestMediaKeySystemAccess(scriptState, keySystem, supportedConfigurations); |
| +} |
| + |
| +ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( |
| + ScriptState* scriptState, |
| + Navigator& navigator, |
| + const String& keySystem, |
| + const Vector<MediaKeySystemOptions>& supportedConfigurations) |
| +{ |
| + // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#requestmediakeysystemaccess |
| + // When this method is invoked, the user agent must run the following steps: |
| + // 1. If keySystem is an empty string, return a promise rejected with a |
| + // new DOMException whose name is InvalidAccessError. |
| + if (keySystem.isEmpty()) { |
| + return ScriptPromise::rejectWithDOMException( |
| + scriptState, DOMException::create(InvalidAccessError, "The keySystem parameter is empty.")); |
| + } |
| + |
| + // 2. If supportedConfigurations was provided and is empty, return a |
| + // promise rejected with a new DOMException whose name is |
| + // InvalidAccessError. |
| + if (!supportedConfigurations.size()) { |
| + return ScriptPromise::rejectWithDOMException( |
| + scriptState, DOMException::create(InvalidAccessError, "The supportedConfigurations parameter is empty.")); |
| + } |
| + |
| + // Remainder of steps handled in common routine below. |
| + return NavigatorRequestMediaKeySystemAccess::from(navigator).requestMediaKeySystemAccess( |
| + scriptState, keySystem, supportedConfigurations); |
| +} |
| + |
| +ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( |
| + ScriptState* scriptState, |
| + const String& keySystem, |
| + const Vector<MediaKeySystemOptions>& supportedConfigurations) |
| +{ |
| + // Continued from above. |
| + // 3. If keySystem is not one of the Key Systems supported by the user |
| + // agent, return a promise rejected with a new DOMException whose name |
| + // is NotSupportedError. String comparison is case-sensitive. |
| + if (!isKeySystemSupportedWithContentType(keySystem, "")) { |
| + return ScriptPromise::rejectWithDOMException( |
| + scriptState, DOMException::create(NotSupportedError, "The key system specified is not supported.")); |
| + } |
| + |
| + // 4. Let promise be a new promise. |
| + // 5. Asynchronously create and initialize the MediaKeySystemAccess object. |
|
ddorwin
2014/10/22 22:18:54
It's really determine support and ....
jrummell
2014/10/23 01:20:03
Done.
|
| + // 6. Return promise. |
| + return MediaKeySystemAccessInitializer::create(scriptState, keySystem, supportedConfigurations); |
| +} |
| + |
| +const char* NavigatorRequestMediaKeySystemAccess::supplementName() |
| +{ |
| + return "RequestMediaKeySystemAccess"; |
| +} |
| + |
| +void NavigatorRequestMediaKeySystemAccess::trace(Visitor* visitor) |
| +{ |
| + WillBeHeapSupplement<Navigator>::trace(visitor); |
| +} |
| + |
| +} // namespace blink |