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

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: Rebase Created 8 years, 4 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 | « webkit/media/crypto/proxy_decryptor.h ('k') | webkit/media/crypto/proxy_decryptor_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..c71c6bdea93ad133f450585892b27626756984ca 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,13 +46,27 @@ 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,
WebKit::WebFrame* web_frame)
: client_(decryptor_client),
web_media_player_client_(web_media_player_client),
- web_frame_(web_frame) {
+ web_frame_(web_frame),
+ stopped_(false) {
}
ProxyDecryptor::~ProxyDecryptor() {
@@ -58,12 +77,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 +97,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);
@@ -98,15 +135,49 @@ void ProxyDecryptor::Decrypt(
media::Decryptor* decryptor = NULL;
{
base::AutoLock auto_lock(lock_);
+ if (stopped_) {
+ DVLOG(1) << "Decrypt(): fire decrypt callbacks with kError.";
+ decrypt_cb.Run(kError, NULL);
+ return;
+ }
decryptor = decryptor_.get();
+ 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;
+ }
}
- if (!decryptor) {
- DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized.";
- decrypt_cb.Run(kError, NULL);
- return;
+
+ decryptor->Decrypt(encrypted, base::Bind(
+ &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this),
+ base::MessageLoopProxy::current(), encrypted, decrypt_cb));
+}
+
+void ProxyDecryptor::Stop() {
+ DVLOG(1) << "AddKey()";
+
+ std::vector<base::Closure> closures_to_run;
+ {
+ base::AutoLock auto_lock(lock_);
+ if (decryptor_.get())
+ decryptor_->Stop();
+ stopped_ = true;
+ std::swap(pending_decrypt_closures_, closures_to_run);
}
- decryptor->Decrypt(encrypted, decrypt_cb);
+ for (std::vector<base::Closure>::iterator iter = closures_to_run.begin();
+ iter != closures_to_run.end();
+ ++iter) {
+ iter->Run();
+ }
}
scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor(
@@ -141,4 +212,62 @@ 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;
+ }
+
+ {
+ base::AutoLock auto_lock(lock_);
+ if (stopped_) {
+ DVLOG(1) << "DecryptOnMessageLoop(): fire decrypt callbacks with kError.";
+ decrypt_cb.Run(kError, NULL);
+ 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_);
+ if (stopped_) {
+ DVLOG(1) << "OnBufferDecrypted(): fire decrypt callbacks with kError.";
+ decrypt_cb.Run(kError, NULL);
+ return;
+ }
+ 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
« no previous file with comments | « webkit/media/crypto/proxy_decryptor.h ('k') | webkit/media/crypto/proxy_decryptor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698