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

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

Issue 563083002: Implement MediaKeys.setServerCertificate() (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 3 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
« no previous file with comments | « Source/modules/encryptedmedia/MediaKeys.h ('k') | Source/modules/encryptedmedia/MediaKeys.idl » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/modules/encryptedmedia/MediaKeys.cpp
diff --git a/Source/modules/encryptedmedia/MediaKeys.cpp b/Source/modules/encryptedmedia/MediaKeys.cpp
index 462eef5c603456349d44dba35b48696ece90ca1c..b9196ae81bc8d27289604bbec963e4c333fd8486 100644
--- a/Source/modules/encryptedmedia/MediaKeys.cpp
+++ b/Source/modules/encryptedmedia/MediaKeys.cpp
@@ -35,6 +35,7 @@
#include "modules/encryptedmedia/MediaKeyMessageEvent.h"
#include "modules/encryptedmedia/MediaKeySession.h"
#include "modules/encryptedmedia/MediaKeysController.h"
+#include "modules/encryptedmedia/SimpleContentDecryptionModuleResult.h"
#include "platform/ContentType.h"
#include "platform/Logging.h"
#include "platform/MIMETypeRegistry.h"
@@ -72,6 +73,46 @@ static ScriptPromise createRejectedPromise(ScriptState* scriptState, ExceptionCo
return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(error, errorMessage));
}
+// A class holding a pending action.
+class MediaKeys::PendingAction : public GarbageCollectedFinalized<MediaKeys::PendingAction> {
+public:
+ const Persistent<ContentDecryptionModuleResult> result() const
+ {
+ return m_result;
+ }
+
+ const RefPtr<ArrayBuffer> data() const
+ {
+ return m_data;
+ }
+
+ static PendingAction* CreatePendingSetServerCertificate(ContentDecryptionModuleResult* result, PassRefPtr<ArrayBuffer> serverCertificate)
+ {
+ ASSERT(result);
+ ASSERT(serverCertificate);
+ return new PendingAction(result, serverCertificate);
+ }
+
+ ~PendingAction()
+ {
+ }
+
+ void trace(Visitor* visitor)
+ {
+ visitor->trace(m_result);
+ }
+
+private:
+ PendingAction(ContentDecryptionModuleResult* result, PassRefPtr<ArrayBuffer> data)
+ : m_result(result)
+ , m_data(data)
+ {
+ }
+
+ const Member<ContentDecryptionModuleResult> m_result;
+ const RefPtr<ArrayBuffer> m_data;
+};
+
// This class allows a MediaKeys object to be created asynchronously.
class MediaKeysInitializer : public ScriptPromiseResolver {
WTF_MAKE_NONCOPYABLE(MediaKeysInitializer);
@@ -177,6 +218,7 @@ MediaKeys::MediaKeys(ExecutionContext* context, const String& keySystem, PassOwn
: ContextLifecycleObserver(context)
, m_keySystem(keySystem)
, m_cdm(cdm)
+ , m_timer(this, &MediaKeys::timerFired)
{
WTF_LOG(Media, "MediaKeys(%p)::MediaKeys", this);
@@ -210,6 +252,53 @@ MediaKeySession* MediaKeys::createSession(ScriptState* scriptState, const String
return MediaKeySession::create(scriptState, this, sessionType);
}
+ScriptPromise MediaKeys::setServerCertificate(ScriptState* scriptState, ArrayBuffer* serverCertificate)
+{
+ RefPtr<ArrayBuffer> serverCertificateCopy = ArrayBuffer::create(serverCertificate->data(), serverCertificate->byteLength());
+ return setServerCertificateInternal(scriptState, serverCertificateCopy.release());
+}
+
+ScriptPromise MediaKeys::setServerCertificate(ScriptState* scriptState, ArrayBufferView* serverCertificate)
+{
+ RefPtr<ArrayBuffer> serverCertificateCopy = ArrayBuffer::create(serverCertificate->baseAddress(), serverCertificate->byteLength());
+ return setServerCertificateInternal(scriptState, serverCertificateCopy.release());
+}
+
+ScriptPromise MediaKeys::setServerCertificateInternal(ScriptState* scriptState, PassRefPtr<ArrayBuffer> serverCertificate)
+{
+ // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-setservercertificate:
+ // The setServerCertificate(serverCertificate) method provides a server
+ // certificate to be used to encrypt messages to the license server.
+ // It must run the following steps:
+ // 1. If serverCertificate is an empty array, return a promise rejected
+ // with a new DOMException whose name is "InvalidAccessError".
+ if (!serverCertificate->byteLength()) {
+ return ScriptPromise::rejectWithDOMException(
+ scriptState, DOMException::create(InvalidAccessError, "The serverCertificate parameter is empty."));
+ }
+
+ // 2. If the keySystem does not support server certificates, return a
+ // promise rejected with a new DOMException whose name is
+ // "NotSupportedError".
+ // (Let the CDM decide whether to support this or not.)
+
+ // 3. Let certificate be a copy of the contents of the serverCertificate
+ // parameter.
+ // (Done in caller.)
+
+ // 4. Let promise be a new promise.
+ SimpleContentDecryptionModuleResult* result = new SimpleContentDecryptionModuleResult(scriptState);
+ ScriptPromise promise = result->promise();
+
+ // 5. Run the following steps asynchronously (documented in timerFired()).
+ m_pendingActions.append(PendingAction::CreatePendingSetServerCertificate(result, serverCertificate));
sandersd (OOO until July 31) 2014/09/11 23:37:13 If the Chromium promises implementation is correct
jrummell 2014/09/12 20:49:03 The problem is that ClearKey will resolve the prom
ddorwin 2014/09/15 23:10:56 As discussed, let's keep it simple, consistent wit
jrummell 2014/09/17 23:39:24 Acknowledged.
+ if (!m_timer.isActive())
+ m_timer.startOneShot(0, FROM_HERE);
+
+ // 6. Return promise.
+ return promise;
+}
+
bool MediaKeys::isTypeSupported(const String& keySystem, const String& contentType)
{
WTF_LOG(Media, "MediaKeys::isTypeSupported(%s, %s)", keySystem.ascii().data(), contentType.ascii().data());
@@ -232,6 +321,32 @@ bool MediaKeys::isTypeSupported(const String& keySystem, const String& contentTy
return isKeySystemSupportedWithContentType(keySystem, contentType);
}
+void MediaKeys::timerFired(Timer<MediaKeys>*)
+{
+ ASSERT(m_pendingActions.size());
+
+ // Resolving promises now run synchronously and may result in additional
ddorwin 2014/09/15 23:10:56 "now"? I assume this was inspired by the change in
jrummell 2014/09/17 23:39:24 Comment removed.
+ // actions getting added to the queue. As a result, swap the queue to
ddorwin 2014/09/15 23:10:56 nit: s/As a result,/Therefore,/
jrummell 2014/09/17 23:39:24 Changed.
+ // a local copy to avoid problems if this happens.
+ HeapDeque<Member<PendingAction> > pendingActions;
+ pendingActions.swap(m_pendingActions);
+
+ while (!pendingActions.isEmpty()) {
+ PendingAction* action = pendingActions.takeFirst();
+ WTF_LOG(Media, "MediaKeys(%p)::timerFired: Certificate", this);
+
+ // 5.1 Let cdm be the cdm during the initialization of this object.
+ WebContentDecryptionModule* cdm = contentDecryptionModule();
+
+ // 5.2 Use the cdm to process certificate.
+ cdm->setServerCertificate(static_cast<unsigned char*>(action->data()->data()), action->data()->byteLength(), action->result()->result());
+ // 5.3 If any of the preceding steps failed, reject promise with a
+ // new DOMException whose name is the appropriate error name.
+ // 5.4 Resolve promise.
+ // These are handled by Chromium and the CDM.
ddorwin 2014/09/15 23:10:56 Add () as elsewhere?
jrummell 2014/09/17 23:39:24 Done.
+ }
+}
+
WebContentDecryptionModule* MediaKeys::contentDecryptionModule()
{
return m_cdm.get();
@@ -239,6 +354,7 @@ WebContentDecryptionModule* MediaKeys::contentDecryptionModule()
void MediaKeys::trace(Visitor* visitor)
{
+ visitor->trace(m_pendingActions);
}
void MediaKeys::contextDestroyed()
« no previous file with comments | « Source/modules/encryptedmedia/MediaKeys.h ('k') | Source/modules/encryptedmedia/MediaKeys.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698