Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Unified Diff: Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp

Issue 665213002: Implement navigator.requestMediaKeySystemAccess() (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: update Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..5a2db08bcfe3d736fcca207b843d4b0b4b2b47ad
--- /dev/null
+++ b/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
@@ -0,0 +1,270 @@
+// 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"
+#include "wtf/text/WTFString.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);
+}
+
+const char* mediaKeysRequirementValidValues[] = { "required", "optional", "disallowed" };
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.
+
+static bool ValidMediaKeysRequirement(const String& itemValue)
ddorwin 2014/10/23 18:02:31 IsV...
jrummell 2014/10/23 22:13:16 Done.
+{
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(mediaKeysRequirementValidValues); ++i) {
+ if (mediaKeysRequirementValidValues[i] == itemValue)
+ return true;
+ }
+ return false;
+}
+
+MediaKeySystemOptions ConvertDictionaryIntoMediaKeySystemOptions(Dictionary& dictionary, ExceptionState& exceptionState)
+{
+ MediaKeySystemOptions result;
+ String itemValue;
+
+ if (DictionaryHelper::get(dictionary, "initDataType", itemValue))
+ result.setInitDataType(itemValue);
+
+ if (DictionaryHelper::get(dictionary, "audioType", itemValue))
+ result.setAudioType(itemValue);
+
+ if (DictionaryHelper::get(dictionary, "audioCapability", itemValue))
+ result.setAudioCapability(itemValue);
+
+ if (DictionaryHelper::get(dictionary, "videoType", itemValue))
+ result.setVideoType(itemValue);
+
+ if (DictionaryHelper::get(dictionary, "videoCapability", itemValue))
+ result.setVideoCapability(itemValue);
+
+ if (DictionaryHelper::get(dictionary, "uniqueidentifier", itemValue)) {
+ if (!ValidMediaKeysRequirement(itemValue))
+ exceptionState.throwTypeError("Invalid MediaKeysRequirement value for 'uniqueidentifier'.");
+ result.setUniqueidentifier(itemValue);
+ }
+
+ if (DictionaryHelper::get(dictionary, "stateful", itemValue)) {
+ if (!ValidMediaKeysRequirement(itemValue))
+ exceptionState.throwTypeError("Invalid MediaKeysRequirement value for 'stateful'.");
+ result.setStateful(itemValue);
+ }
+
+ return result;
+}
+
+// This class allows capabilities to be checked and a MediaKeySystemAccess
+// object to be created asynchronously.
+class MediaKeySystemAccessInitializer : public ScriptPromiseResolver {
+ 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.
+ // (Handled by Chromium.)
+
+ // 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.
+ return NavigatorRequestMediaKeySystemAccess::from(navigator).requestMediaKeySystemAccess(scriptState, keySystem, Vector<MediaKeySystemOptions>());
+}
+
+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 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.
+ // initialize the MediaKeySystemAccess object.
+ // 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

Powered by Google App Engine
This is Rietveld 408576698