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

Unified Diff: webkit/media/crypto/proxy_decryptor.cc

Issue 10822026: Implement "Key Presence" step in "Encrypted Block Encounted" algorithm in EME. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix broken ChunkDemuxerTest due to null MessageLoop::Current() Created 8 years, 5 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: webkit/media/crypto/proxy_decryptor.cc
diff --git a/webkit/media/crypto/proxy_decryptor.cc b/webkit/media/crypto/proxy_decryptor.cc
index 0b786552b577ea199d042517195a2a20ffb05cb1..8dd320fd3be649ae14570cc3c75b4645a5aa789a 100644
--- a/webkit/media/crypto/proxy_decryptor.cc
+++ b/webkit/media/crypto/proxy_decryptor.cc
@@ -4,7 +4,12 @@
#include "webkit/media/crypto/proxy_decryptor.h"
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
+#include "base/message_loop_proxy.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decryptor_client.h"
#include "media/crypto/aes_decryptor.h"
@@ -41,6 +46,19 @@ static scoped_refptr<webkit::ppapi::PluginInstance> CreatePluginInstance(
return ppapi_plugin->instance();
}
+// TODO(xhwang): Simplify this function. This is mostly caused by the fact that
+// we need to copy a scoped_array<uint8>.
+static void FireNeedKey(media::DecryptorClient* client,
+ const scoped_refptr<media::DecoderBuffer>& encrypted) {
+ DCHECK(client);
+ DCHECK(encrypted);
+ DCHECK(encrypted->GetDecryptConfig());
+ std::string key_id = encrypted->GetDecryptConfig()->key_id();
+ scoped_array<uint8> key_id_array(new uint8[key_id.size()]);
+ memcpy(key_id_array.get(), key_id.data(), key_id.size());
+ client->NeedKey("", "", key_id_array.Pass(), key_id.size());
+}
+
ProxyDecryptor::ProxyDecryptor(
media::DecryptorClient* decryptor_client,
WebKit::WebMediaPlayerClient* web_media_player_client,
@@ -58,12 +76,12 @@ void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system,
int init_data_length) {
// We do not support run-time switching of decryptors. GenerateKeyRequest()
// only creates a new decryptor when |decryptor_| is not initialized.
+ DVLOG(1) << "GenerateKeyRequest: key_system = " << key_system;
if (!decryptor_.get()) {
base::AutoLock auto_lock(lock_);
decryptor_ = CreateDecryptor(key_system);
}
- DCHECK(client_);
if (!decryptor_.get()) {
client_->KeyError(key_system, "", media::Decryptor::kUnknownError, 0);
return;
@@ -78,14 +96,32 @@ void ProxyDecryptor::AddKey(const std::string& key_system,
const uint8* init_data,
int init_data_length,
const std::string& session_id) {
+ DVLOG(1) << "AddKey()";
+
// WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
DCHECK(decryptor_.get());
decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length,
session_id);
+
+ std::vector<base::Closure> closures_to_run;
+ {
+ base::AutoLock auto_lock(lock_);
+ std::swap(pending_decrypt_closures_, closures_to_run);
+ }
+
+ // Fire all pending callbacks here because only the |decryptor_| knows if the
+ // pending buffers can be decrypted or not.
+ for (std::vector<base::Closure>::iterator iter = closures_to_run.begin();
+ iter != closures_to_run.end();
+ ++iter) {
+ iter->Run();
+ }
}
void ProxyDecryptor::CancelKeyRequest(const std::string& key_system,
const std::string& session_id) {
+ DVLOG(1) << "CancelKeyRequest()";
+
// WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
DCHECK(decryptor_.get());
decryptor_->CancelKeyRequest(key_system, session_id);
@@ -99,14 +135,24 @@ void ProxyDecryptor::Decrypt(
{
base::AutoLock auto_lock(lock_);
decryptor = decryptor_.get();
- }
- if (!decryptor) {
- DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized.";
- decrypt_cb.Run(kError, NULL);
- return;
+ if (!decryptor) {
+ DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized.";
+ pending_decrypt_closures_.push_back(
+ base::Bind(&ProxyDecryptor::DecryptOnMessageLoop,
+ base::Unretained(this),
+ base::MessageLoopProxy::current(), encrypted,
+ decrypt_cb));
+ // TODO(xhwang): The same NeedKey may be fired here and multiple times in
+ // OnBufferDecrypted(). While the spec says only one NeedKey should be
+ // fired. Leave them as is since the spec about this may change.
+ FireNeedKey(client_, encrypted);
+ return;
+ }
}
- decryptor->Decrypt(encrypted, decrypt_cb);
+ decryptor->Decrypt(encrypted, base::Bind(
+ &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this),
+ base::MessageLoopProxy::current(), encrypted, decrypt_cb));
}
scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor(
@@ -141,4 +187,47 @@ scoped_ptr<media::Decryptor> ProxyDecryptor::CreateDecryptor(
return CreatePpapiDecryptor(key_system);
}
+void ProxyDecryptor::DecryptOnMessageLoop(
+ const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
+ const scoped_refptr<media::DecoderBuffer>& encrypted,
+ const media::Decryptor::DecryptCB& decrypt_cb) {
+ DCHECK(decryptor_.get());
+
+ if (!message_loop_proxy->BelongsToCurrentThread()) {
+ message_loop_proxy->PostTask(FROM_HERE, base::Bind(
+ &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
+ message_loop_proxy, encrypted, decrypt_cb));
+ return;
+ }
+
+ decryptor_->Decrypt(encrypted, base::Bind(&ProxyDecryptor::OnBufferDecrypted,
+ base::Unretained(this), message_loop_proxy, encrypted, decrypt_cb));
+}
+
+void ProxyDecryptor::OnBufferDecrypted(
+ const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
+ const scoped_refptr<media::DecoderBuffer>& encrypted,
+ const media::Decryptor::DecryptCB& decrypt_cb,
+ media::Decryptor::DecryptStatus status,
+ const scoped_refptr<media::DecoderBuffer>& decrypted) {
+ if (status == media::Decryptor::kSuccess ||
+ status == media::Decryptor::kError) {
+ decrypt_cb.Run(status, decrypted);
+ return;
+ }
+
+ DCHECK_EQ(status, media::Decryptor::kNoKey);
+ DVLOG(1) << "OnBufferDecrypted(): kNoKey fired";
+ {
+ base::AutoLock auto_lock(lock_);
+ pending_decrypt_closures_.push_back(base::Bind(
+ &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
+ message_loop_proxy, encrypted, decrypt_cb));
+ }
+ // TODO(xhwang): The same NeedKey may be fired multiple times here and also
+ // in Decrypt(). While the spec says only one NeedKey should be fired. Leave
+ // them as is since the spec about this may change.
+ FireNeedKey(client_, encrypted);
+}
+
} // namespace webkit_media

Powered by Google App Engine
This is Rietveld 408576698