summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjrummell@chromium.org <jrummell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-15 03:05:54 +0000
committerjrummell@chromium.org <jrummell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-15 03:08:33 +0000
commit1e52c2922ac0b9b3483cc6c5cb2c51c472773b57 (patch)
tree832c05ceebb1bac77477a0c661bd0b3278a113e6
parent0fd76c553e9b03357d11e158866cbdf3f0617514 (diff)
downloadchromium_src-1e52c2922ac0b9b3483cc6c5cb2c51c472773b57.zip
chromium_src-1e52c2922ac0b9b3483cc6c5cb2c51c472773b57.tar.gz
chromium_src-1e52c2922ac0b9b3483cc6c5cb2c51c472773b57.tar.bz2
Update ClearKey to support CDM_6
This change adds support for GetUsableKeyIds() and RemoveSession(), and renames ReleaseSession() to CloseSession(). There are also changes due to the Ready event no longer being generated by the CDM interface. BUG=358271,351139 TEST=encrypted-media layout tests and browser_tests for encrypted media pass Review URL: https://codereview.chromium.org/448893002 Cr-Commit-Position: refs/heads/master@{#289755} git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289755 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/renderer/media/crypto/ppapi_decryptor.cc40
-rw-r--r--content/renderer/media/crypto/proxy_decryptor.cc32
-rw-r--r--content/renderer/media/crypto/proxy_decryptor.h9
-rw-r--r--media/base/cdm_promise.cc5
-rw-r--r--media/base/cdm_promise.h6
-rw-r--r--media/base/media_keys.h2
-rw-r--r--media/cdm/aes_decryptor.cc21
-rw-r--r--media/cdm/aes_decryptor.h3
-rw-r--r--media/cdm/aes_decryptor_unittest.cc100
-rw-r--r--media/cdm/ppapi/external_clear_key/clear_key_cdm.cc73
-rw-r--r--media/cdm/ppapi/external_clear_key/clear_key_cdm.h31
-rw-r--r--media/cdm/ppapi/external_clear_key/clear_key_cdm_common.h2
12 files changed, 272 insertions, 52 deletions
diff --git a/content/renderer/media/crypto/ppapi_decryptor.cc b/content/renderer/media/crypto/ppapi_decryptor.cc
index dd07aaa..8f39c06 100644
--- a/content/renderer/media/crypto/ppapi_decryptor.cc
+++ b/content/renderer/media/crypto/ppapi_decryptor.cc
@@ -55,6 +55,37 @@ class SessionUpdatedPromise : public media::SimpleCdmPromise {
base::Closure additional_resolve_cb_;
};
+// This class is needed so that resolving a SessionLoaded() promise triggers
+// playback of the stream. It intercepts the resolve() call to invoke an
+// additional callback. This is only needed until KeysChange event gets passed
+// through Pepper.
+class SessionLoadedPromise : public media::NewSessionCdmPromise {
+ public:
+ SessionLoadedPromise(scoped_ptr<media::NewSessionCdmPromise> caller_promise,
+ base::Closure additional_resolve_cb)
+ : caller_promise_(caller_promise.Pass()),
+ additional_resolve_cb_(additional_resolve_cb) {}
+
+ virtual void resolve(const std::string& web_session_id) OVERRIDE {
+ DCHECK(is_pending_);
+ is_pending_ = false;
+ additional_resolve_cb_.Run();
+ caller_promise_->resolve(web_session_id);
+ }
+
+ virtual void reject(media::MediaKeys::Exception exception_code,
+ uint32 system_code,
+ const std::string& error_message) OVERRIDE {
+ DCHECK(is_pending_);
+ is_pending_ = false;
+ caller_promise_->reject(exception_code, system_code, error_message);
+ }
+
+ protected:
+ scoped_ptr<media::NewSessionCdmPromise> caller_promise_;
+ base::Closure additional_resolve_cb_;
+};
+
scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
const std::string& key_system,
const GURL& security_origin,
@@ -147,7 +178,14 @@ void PpapiDecryptor::LoadSession(
return;
}
- CdmDelegate()->LoadSession(web_session_id, promise.Pass());
+ scoped_ptr<SessionLoadedPromise> session_loaded_promise(
+ new SessionLoadedPromise(promise.Pass(),
+ base::Bind(&PpapiDecryptor::ResumePlayback,
+ weak_ptr_factory_.GetWeakPtr())));
+
+ CdmDelegate()->LoadSession(
+ web_session_id,
+ session_loaded_promise.PassAs<media::NewSessionCdmPromise>());
}
void PpapiDecryptor::UpdateSession(
diff --git a/content/renderer/media/crypto/proxy_decryptor.cc b/content/renderer/media/crypto/proxy_decryptor.cc
index bd9a0db..0502680 100644
--- a/content/renderer/media/crypto/proxy_decryptor.cc
+++ b/content/renderer/media/crypto/proxy_decryptor.cc
@@ -102,21 +102,25 @@ bool ProxyDecryptor::GenerateKeyRequest(const std::string& content_type,
const char kPrefixedApiPersistentSessionHeader[] = "PERSISTENT|";
const char kPrefixedApiLoadSessionHeader[] = "LOAD_SESSION|";
- bool loadSession =
- HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader);
- bool persistent = HasHeader(
- init_data, init_data_length, kPrefixedApiPersistentSessionHeader);
+ SessionCreationType session_creation_type = TemporarySession;
+ if (HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader)) {
+ session_creation_type = LoadSession;
+ } else if (HasHeader(init_data,
+ init_data_length,
+ kPrefixedApiPersistentSessionHeader)) {
+ session_creation_type = PersistentSession;
+ }
scoped_ptr<media::NewSessionCdmPromise> promise(
new media::NewSessionCdmPromise(
base::Bind(&ProxyDecryptor::SetSessionId,
weak_ptr_factory_.GetWeakPtr(),
- persistent || loadSession),
+ session_creation_type),
base::Bind(&ProxyDecryptor::OnSessionError,
weak_ptr_factory_.GetWeakPtr(),
std::string()))); // No session id until created.
- if (loadSession) {
+ if (session_creation_type == LoadSession) {
media_keys_->LoadSession(
std::string(reinterpret_cast<const char*>(
init_data + strlen(kPrefixedApiLoadSessionHeader)),
@@ -126,8 +130,9 @@ bool ProxyDecryptor::GenerateKeyRequest(const std::string& content_type,
}
media::MediaKeys::SessionType session_type =
- persistent ? media::MediaKeys::PERSISTENT_SESSION
- : media::MediaKeys::TEMPORARY_SESSION;
+ session_creation_type == PersistentSession
+ ? media::MediaKeys::PERSISTENT_SESSION
+ : media::MediaKeys::TEMPORARY_SESSION;
// Convert MIME types used in the prefixed implementation.
std::string init_data_type;
@@ -298,9 +303,16 @@ void ProxyDecryptor::OnSessionError(const std::string& web_session_id,
key_error_cb_.Run(web_session_id, error_code, system_code);
}
-void ProxyDecryptor::SetSessionId(bool persistent,
+void ProxyDecryptor::SetSessionId(SessionCreationType session_type,
const std::string& web_session_id) {
- active_sessions_.insert(std::make_pair(web_session_id, persistent));
+ // Loaded sessions are considered persistent.
+ bool is_persistent =
+ session_type == PersistentSession || session_type == LoadSession;
+ active_sessions_.insert(std::make_pair(web_session_id, is_persistent));
+
+ // For LoadSession(), generate the SessionReady event.
+ if (session_type == LoadSession)
+ OnSessionReady(web_session_id);
}
} // namespace content
diff --git a/content/renderer/media/crypto/proxy_decryptor.h b/content/renderer/media/crypto/proxy_decryptor.h
index e4fd7ea..b1e736d 100644
--- a/content/renderer/media/crypto/proxy_decryptor.h
+++ b/content/renderer/media/crypto/proxy_decryptor.h
@@ -96,8 +96,15 @@ class ProxyDecryptor {
uint32 system_code,
const std::string& error_message);
+ enum SessionCreationType {
+ TemporarySession,
+ PersistentSession,
+ LoadSession
+ };
+
// Called when a session is actually created or loaded.
- void SetSessionId(bool persistent, const std::string& web_session_id);
+ void SetSessionId(SessionCreationType session_type,
+ const std::string& web_session_id);
#if defined(ENABLE_PEPPER_CDMS)
// Callback to create the Pepper plugin.
diff --git a/media/base/cdm_promise.cc b/media/base/cdm_promise.cc
index e57d4f4..13ee760 100644
--- a/media/base/cdm_promise.cc
+++ b/media/base/cdm_promise.cc
@@ -81,6 +81,10 @@ CdmPromiseTemplate<T>::CdmPromiseTemplate(
}
template <typename T>
+CdmPromiseTemplate<T>::CdmPromiseTemplate() {
+}
+
+template <typename T>
CdmPromiseTemplate<T>::~CdmPromiseTemplate() {
DCHECK(!is_pending_);
}
@@ -131,5 +135,6 @@ void CdmPromiseTemplate<void>::resolve() {
// Explicit template instantiation for the Promises needed.
template class MEDIA_EXPORT CdmPromiseTemplate<std::string>;
+template class MEDIA_EXPORT CdmPromiseTemplate<KeyIdsVector>;
} // namespace media
diff --git a/media/base/cdm_promise.h b/media/base/cdm_promise.h
index 2d45cf2..14f79f8 100644
--- a/media/base/cdm_promise.h
+++ b/media/base/cdm_promise.h
@@ -81,6 +81,12 @@ class MEDIA_EXPORT CdmPromiseTemplate : public CdmPromise {
virtual ~CdmPromiseTemplate();
virtual void resolve(const T& result);
+ protected:
+ // Allow subclasses to completely override the implementation.
+ // TODO(jrummell): Remove when derived class SessionLoadedPromise
+ // (in ppapi_decryptor.cc) is no longer needed.
+ CdmPromiseTemplate();
+
private:
base::Callback<void(const T&)> resolve_cb_;
diff --git a/media/base/media_keys.h b/media/base/media_keys.h
index d581ae4..063e54b 100644
--- a/media/base/media_keys.h
+++ b/media/base/media_keys.h
@@ -23,6 +23,8 @@ class CdmPromiseTemplate;
typedef CdmPromiseTemplate<std::string> NewSessionCdmPromise;
typedef CdmPromiseTemplate<void> SimpleCdmPromise;
+typedef std::vector<std::vector<uint8> > KeyIdsVector;
+typedef CdmPromiseTemplate<KeyIdsVector> KeyIdsPromise;
// Performs media key operations.
//
diff --git a/media/cdm/aes_decryptor.cc b/media/cdm/aes_decryptor.cc
index 3530c3e..daafb1e 100644
--- a/media/cdm/aes_decryptor.cc
+++ b/media/cdm/aes_decryptor.cc
@@ -53,6 +53,10 @@ class AesDecryptor::SessionIdDecryptionKeyMap {
return key_list_.begin()->second;
}
+ bool Contains(const std::string& web_session_id) {
+ return Find(web_session_id) != key_list_.end();
+ }
+
private:
// Searches the list for an element with |web_session_id|.
KeyList::iterator Find(const std::string& web_session_id);
@@ -315,6 +319,23 @@ void AesDecryptor::UpdateSession(const std::string& web_session_id,
promise->resolve();
}
+void AesDecryptor::GetUsableKeyIds(const std::string& web_session_id,
+ scoped_ptr<KeyIdsPromise> promise) {
+ // Since |web_session_id| is not provided by the user, this should never
+ // happen.
+ DCHECK(valid_sessions_.find(web_session_id) != valid_sessions_.end());
+
+ KeyIdsVector keyids;
+ base::AutoLock auto_lock(key_map_lock_);
+ for (KeyIdToSessionKeysMap::iterator it = key_map_.begin();
+ it != key_map_.end();
+ ++it) {
+ if (it->second->Contains(web_session_id))
+ keyids.push_back(std::vector<uint8>(it->first.begin(), it->first.end()));
+ }
+ promise->resolve(keyids);
+}
+
void AesDecryptor::ReleaseSession(const std::string& web_session_id,
scoped_ptr<SimpleCdmPromise> promise) {
// Validate that this is a reference to an active session and then forget it.
diff --git a/media/cdm/aes_decryptor.h b/media/cdm/aes_decryptor.h
index 3a17770..dc08bb3 100644
--- a/media/cdm/aes_decryptor.h
+++ b/media/cdm/aes_decryptor.h
@@ -67,6 +67,9 @@ class MEDIA_EXPORT AesDecryptor : public MediaKeys, public Decryptor {
virtual void ResetDecoder(StreamType stream_type) OVERRIDE;
virtual void DeinitializeDecoder(StreamType stream_type) OVERRIDE;
+ void GetUsableKeyIds(const std::string& web_session_id,
+ scoped_ptr<KeyIdsPromise> promise);
+
private:
// TODO(fgalligan): Remove this and change KeyMap to use crypto::SymmetricKey
// as there are no decryptors that are performing an integrity check.
diff --git a/media/cdm/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc
index d2d7ee0..91cd6ac 100644
--- a/media/cdm/aes_decryptor_unittest.cc
+++ b/media/cdm/aes_decryptor_unittest.cc
@@ -220,41 +220,66 @@ class AesDecryptorTest : public testing::Test {
}
protected:
- void OnResolveWithSession(PromiseResult expected,
+ void OnResolveWithSession(PromiseResult expected_result,
const std::string& web_session_id) {
- EXPECT_EQ(expected, RESOLVED);
+ EXPECT_EQ(expected_result, RESOLVED) << "Unexpectedly resolved.";
EXPECT_GT(web_session_id.length(), 0ul);
web_session_id_ = web_session_id;
}
- void OnResolve(PromiseResult expected) {
- EXPECT_EQ(expected, RESOLVED);
+ void OnResolve(PromiseResult expected_result) {
+ EXPECT_EQ(expected_result, RESOLVED) << "Unexpectedly resolved.";
}
- void OnReject(PromiseResult expected,
+ void OnResolveWithUsableKeyIds(PromiseResult expected_result,
+ uint32 expected_count,
+ const KeyIdsVector& useable_key_ids) {
+ EXPECT_EQ(expected_result, RESOLVED) << "Unexpectedly resolved.";
+ EXPECT_EQ(expected_count, useable_key_ids.size());
+ useable_key_ids_ = useable_key_ids;
+ }
+
+ void OnReject(PromiseResult expected_result,
MediaKeys::Exception exception_code,
uint32 system_code,
const std::string& error_message) {
- EXPECT_EQ(expected, REJECTED);
+ EXPECT_EQ(expected_result, REJECTED) << "Unexpectedly rejected.";
}
- scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected) {
- scoped_ptr<SimpleCdmPromise> promise(new SimpleCdmPromise(
- base::Bind(
- &AesDecryptorTest::OnResolve, base::Unretained(this), expected),
- base::Bind(
- &AesDecryptorTest::OnReject, base::Unretained(this), expected)));
+ scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected_result) {
+ scoped_ptr<SimpleCdmPromise> promise(
+ new SimpleCdmPromise(base::Bind(&AesDecryptorTest::OnResolve,
+ base::Unretained(this),
+ expected_result),
+ base::Bind(&AesDecryptorTest::OnReject,
+ base::Unretained(this),
+ expected_result)));
return promise.Pass();
}
scoped_ptr<NewSessionCdmPromise> CreateSessionPromise(
- PromiseResult expected) {
+ PromiseResult expected_result) {
scoped_ptr<NewSessionCdmPromise> promise(new NewSessionCdmPromise(
base::Bind(&AesDecryptorTest::OnResolveWithSession,
base::Unretained(this),
- expected),
- base::Bind(
- &AesDecryptorTest::OnReject, base::Unretained(this), expected)));
+ expected_result),
+ base::Bind(&AesDecryptorTest::OnReject,
+ base::Unretained(this),
+ expected_result)));
+ return promise.Pass();
+ }
+
+ scoped_ptr<KeyIdsPromise> CreateUsableKeyIdsPromise(
+ PromiseResult expected_result,
+ uint32 expected_count) {
+ scoped_ptr<KeyIdsPromise> promise(new KeyIdsPromise(
+ base::Bind(&AesDecryptorTest::OnResolveWithUsableKeyIds,
+ base::Unretained(this),
+ expected_result,
+ expected_count),
+ base::Bind(&AesDecryptorTest::OnReject,
+ base::Unretained(this),
+ expected_result)));
return promise.Pass();
}
@@ -292,6 +317,23 @@ class AesDecryptorTest : public testing::Test {
CreatePromise(result));
}
+ void GetUsableKeyIdsAndExpect(const std::string& session_id,
+ PromiseResult expected_result,
+ uint32 expected_count) {
+ decryptor_.GetUsableKeyIds(
+ session_id, CreateUsableKeyIdsPromise(expected_result, expected_count));
+ }
+
+ bool UsableKeyIdsContains(std::vector<uint8> expected) {
+ for (KeyIdsVector::iterator it = useable_key_ids_.begin();
+ it != useable_key_ids_.end();
+ ++it) {
+ if (*it == expected)
+ return true;
+ }
+ return false;
+ }
+
MOCK_METHOD2(BufferDecrypted, void(Decryptor::Status,
const scoped_refptr<DecoderBuffer>&));
@@ -361,6 +403,10 @@ class AesDecryptorTest : public testing::Test {
AesDecryptor::DecryptCB decrypt_cb_;
std::string web_session_id_;
+ // Copy of the vector from the last successful call to
+ // OnResolveWithUsableKeyIds().
+ KeyIdsVector useable_key_ids_;
+
// Constants for testing.
const std::vector<uint8> original_data_;
const std::vector<uint8> encrypted_data_;
@@ -789,4 +835,26 @@ TEST_F(AesDecryptorTest, JWKKey) {
ReleaseSession(session_id);
}
+TEST_F(AesDecryptorTest, GetKeyIds) {
+ std::vector<uint8> key_id1(kKeyId, kKeyId + arraysize(kKeyId));
+ std::vector<uint8> key_id2(kKeyId2, kKeyId2 + arraysize(kKeyId2));
+
+ std::string session_id = CreateSession(key_id_);
+ GetUsableKeyIdsAndExpect(session_id, RESOLVED, 0);
+ EXPECT_FALSE(UsableKeyIdsContains(key_id1));
+ EXPECT_FALSE(UsableKeyIdsContains(key_id2));
+
+ // Add 1 key, verify ID is returned.
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
+ GetUsableKeyIdsAndExpect(session_id, RESOLVED, 1);
+ EXPECT_TRUE(UsableKeyIdsContains(key_id1));
+ EXPECT_FALSE(UsableKeyIdsContains(key_id2));
+
+ // Add second key, verify both IDs returned.
+ UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED);
+ GetUsableKeyIdsAndExpect(session_id, RESOLVED, 2);
+ EXPECT_TRUE(UsableKeyIdsContains(key_id1));
+ EXPECT_TRUE(UsableKeyIdsContains(key_id2));
+}
+
} // namespace media
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
index a643920..e06f41b 100644
--- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
+++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -95,7 +95,7 @@ const char kFileIOTestResultHeader[] = "FILEIOTESTRESULT";
// Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is
// empty, an empty (end-of-stream) media::DecoderBuffer is returned.
static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom(
- const cdm::InputBuffer_1& input_buffer) {
+ const cdm::InputBuffer& input_buffer) {
if (!input_buffer.data) {
DCHECK(!input_buffer.data_size);
return media::DecoderBuffer::CreateEOSBuffer();
@@ -113,7 +113,6 @@ static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom(
subsamples.push_back(subsample);
}
- DCHECK_EQ(input_buffer.data_offset, 0u);
scoped_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig(
std::string(reinterpret_cast<const char*>(input_buffer.key_id),
input_buffer.key_id_size),
@@ -273,6 +272,7 @@ void ClearKeyCdm::LoadSession(uint32 promise_id,
if (std::string(kLoadableWebSessionId) !=
std::string(web_session_id, web_session_id_length)) {
+ // TODO(jrummell): This should be resolved with undefined, not rejected.
std::string message("Incorrect session id specified for LoadSession().");
host_->OnRejectPromise(promise_id,
cdm::kInvalidAccessError,
@@ -298,11 +298,11 @@ void ClearKeyCdm::LoadSession(uint32 promise_id,
void ClearKeyCdm::UpdateSession(uint32 promise_id,
const char* web_session_id,
- uint32_t web_session_id_size,
+ uint32_t web_session_id_length,
const uint8* response,
uint32 response_size) {
DVLOG(1) << __FUNCTION__;
- std::string web_session_str(web_session_id, web_session_id_size);
+ std::string web_session_str(web_session_id, web_session_id_length);
scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
base::Bind(&ClearKeyCdm::OnSessionUpdated,
@@ -320,11 +320,11 @@ void ClearKeyCdm::UpdateSession(uint32 promise_id,
}
}
-void ClearKeyCdm::ReleaseSession(uint32 promise_id,
- const char* web_session_id,
- uint32_t web_session_id_size) {
+void ClearKeyCdm::CloseSession(uint32 promise_id,
+ const char* web_session_id,
+ uint32_t web_session_id_length) {
DVLOG(1) << __FUNCTION__;
- std::string web_session_str(web_session_id, web_session_id_size);
+ std::string web_session_str(web_session_id, web_session_id_length);
scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
base::Bind(&ClearKeyCdm::OnSessionReleased,
@@ -336,6 +336,26 @@ void ClearKeyCdm::ReleaseSession(uint32 promise_id,
decryptor_.ReleaseSession(web_session_str, promise.Pass());
}
+void ClearKeyCdm::RemoveSession(uint32 promise_id,
+ const char* web_session_id,
+ uint32_t web_session_id_length) {
+ DVLOG(1) << __FUNCTION__;
+ // RemoveSession only allowed for persistent sessions.
+ bool is_persistent_session =
+ std::string(kLoadableWebSessionId) ==
+ std::string(web_session_id, web_session_id_length);
+ if (is_persistent_session) {
+ host_->OnResolvePromise(promise_id);
+ } else {
+ std::string message("Not supported for non-persistent sessions.");
+ host_->OnRejectPromise(promise_id,
+ cdm::kInvalidAccessError,
+ 0,
+ message.data(),
+ message.length());
+ }
+}
+
void ClearKeyCdm::SetServerCertificate(uint32 promise_id,
const uint8_t* server_certificate_data,
uint32_t server_certificate_data_size) {
@@ -343,6 +363,19 @@ void ClearKeyCdm::SetServerCertificate(uint32 promise_id,
host_->OnResolvePromise(promise_id);
}
+void ClearKeyCdm::GetUsableKeyIds(uint32_t promise_id,
+ const char* web_session_id,
+ uint32_t web_session_id_length) {
+ std::string web_session_str(web_session_id, web_session_id_length);
+ scoped_ptr<media::KeyIdsPromise> promise(new media::KeyIdsPromise(
+ base::Bind(&ClearKeyCdm::OnUsableKeyIdsObtained,
+ base::Unretained(this),
+ promise_id),
+ base::Bind(
+ &ClearKeyCdm::OnPromiseFailed, base::Unretained(this), promise_id)));
+ decryptor_.GetUsableKeyIds(web_session_str, promise.Pass());
+}
+
void ClearKeyCdm::TimerExpired(void* context) {
if (context == &session_id_for_emulated_loadsession_) {
LoadLoadableSession();
@@ -381,7 +414,7 @@ static void CopyDecryptResults(
*buffer_copy = buffer;
}
-cdm::Status ClearKeyCdm::Decrypt(const cdm::InputBuffer_1& encrypted_buffer,
+cdm::Status ClearKeyCdm::Decrypt(const cdm::InputBuffer& encrypted_buffer,
cdm::DecryptedBlock* decrypted_block) {
DVLOG(1) << "Decrypt()";
DCHECK(encrypted_buffer.data);
@@ -487,7 +520,7 @@ void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) {
}
cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
- const cdm::InputBuffer_1& encrypted_buffer,
+ const cdm::InputBuffer& encrypted_buffer,
cdm::VideoFrame* decoded_frame) {
DVLOG(1) << "DecryptAndDecodeFrame()";
TRACE_EVENT0("media", "ClearKeyCdm::DecryptAndDecodeFrame");
@@ -511,7 +544,7 @@ cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
}
cdm::Status ClearKeyCdm::DecryptAndDecodeSamples(
- const cdm::InputBuffer_1& encrypted_buffer,
+ const cdm::InputBuffer& encrypted_buffer,
cdm::AudioFrames* audio_frames) {
DVLOG(1) << "DecryptAndDecodeSamples()";
@@ -557,7 +590,7 @@ void ClearKeyCdm::ScheduleNextHeartBeat() {
// Prepare the next heartbeat message and set timer.
std::ostringstream msg_stream;
msg_stream << kHeartBeatHeader << " from ClearKey CDM set at time "
- << host_->GetCurrentTime() << ".";
+ << host_->GetCurrentWallTime() << ".";
next_heartbeat_message_ = msg_stream.str();
host_->SetTimer(timer_delay_ms_, &next_heartbeat_message_[0]);
@@ -569,7 +602,7 @@ void ClearKeyCdm::ScheduleNextHeartBeat() {
}
cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer(
- const cdm::InputBuffer_1& encrypted_buffer,
+ const cdm::InputBuffer& encrypted_buffer,
scoped_refptr<media::DecoderBuffer>* decrypted_buffer) {
DCHECK(decrypted_buffer);
scoped_refptr<media::DecoderBuffer> buffer =
@@ -687,15 +720,13 @@ void ClearKeyCdm::OnSessionLoaded(uint32 promise_id,
void ClearKeyCdm::OnSessionUpdated(uint32 promise_id,
const std::string& web_session_id) {
- // OnSessionReady() only called as success for UpdateSession(). However,
- // UpdateSession() also called to finish loading sessions, so handle
+ // UpdateSession() may be called to finish loading sessions, so handle
// appropriately.
if (web_session_id == session_id_for_emulated_loadsession_) {
session_id_for_emulated_loadsession_ = std::string();
// |promise_id| is the LoadSession() promise, so resolve appropriately.
host_->OnResolveNewSessionPromise(
promise_id, kLoadableWebSessionId, strlen(kLoadableWebSessionId));
- host_->OnSessionReady(kLoadableWebSessionId, strlen(kLoadableWebSessionId));
return;
}
@@ -707,6 +738,16 @@ void ClearKeyCdm::OnSessionReleased(uint32 promise_id,
host_->OnResolvePromise(promise_id);
}
+void ClearKeyCdm::OnUsableKeyIdsObtained(uint32 promise_id,
+ const KeyIdsVector& key_ids) {
+ scoped_ptr<cdm::BinaryData[]> result(new cdm::BinaryData[key_ids.size()]);
+ for (uint32 i = 0; i < key_ids.size(); ++i) {
+ result[i].data = key_ids[i].data();
+ result[i].length = key_ids[i].size();
+ }
+ host_->OnResolveKeyIdsPromise(promise_id, result.get(), key_ids.size());
+}
+
void ClearKeyCdm::OnPromiseFailed(uint32 promise_id,
MediaKeys::Exception exception_code,
uint32 system_code,
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.h b/media/cdm/ppapi/external_clear_key/clear_key_cdm.h
index 0288998..c491cd7 100644
--- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.h
+++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.h
@@ -49,15 +49,21 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
uint32_t web_session_id_length,
const uint8* response,
uint32 response_size) OVERRIDE;
- virtual void ReleaseSession(uint32 promise_id,
- const char* web_session_id,
- uint32_t web_session_id_length) OVERRIDE;
+ virtual void CloseSession(uint32 promise_id,
+ const char* web_session_id,
+ uint32_t web_session_id_length) OVERRIDE;
+ virtual void RemoveSession(uint32 promise_id,
+ const char* web_session_id,
+ uint32_t web_session_id_length) OVERRIDE;
+ virtual void GetUsableKeyIds(uint32_t promise_id,
+ const char* web_session_id,
+ uint32_t web_session_id_length) OVERRIDE;
virtual void SetServerCertificate(
uint32 promise_id,
const uint8_t* server_certificate_data,
uint32_t server_certificate_data_size) OVERRIDE;
virtual void TimerExpired(void* context) OVERRIDE;
- virtual cdm::Status Decrypt(const cdm::InputBuffer_1& encrypted_buffer,
+ virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
cdm::DecryptedBlock* decrypted_block) OVERRIDE;
virtual cdm::Status InitializeAudioDecoder(
const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE;
@@ -66,10 +72,10 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE;
virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE;
virtual cdm::Status DecryptAndDecodeFrame(
- const cdm::InputBuffer_1& encrypted_buffer,
+ const cdm::InputBuffer& encrypted_buffer,
cdm::VideoFrame* video_frame) OVERRIDE;
virtual cdm::Status DecryptAndDecodeSamples(
- const cdm::InputBuffer_1& encrypted_buffer,
+ const cdm::InputBuffer& encrypted_buffer,
cdm::AudioFrames* audio_frames) OVERRIDE;
virtual void Destroy() OVERRIDE;
virtual void OnPlatformChallengeResponse(
@@ -94,6 +100,7 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
void OnSessionLoaded(uint32 promise_id, const std::string& web_session_id);
void OnSessionUpdated(uint32 promise_id, const std::string& web_session_id);
void OnSessionReleased(uint32 promise_id, const std::string& web_session_id);
+ void OnUsableKeyIdsObtained(uint32 promise_id, const KeyIdsVector& key_ids);
void OnPromiseFailed(uint32 promise_id,
MediaKeys::Exception exception_code,
uint32 system_code,
@@ -111,7 +118,7 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
// Returns cdm::kDecryptError if any decryption error occurred. In this case
// |decrypted_buffer| should be ignored by the caller.
cdm::Status DecryptToMediaDecoderBuffer(
- const cdm::InputBuffer_1& encrypted_buffer,
+ const cdm::InputBuffer& encrypted_buffer,
scoped_refptr<DecoderBuffer>* decrypted_buffer);
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
@@ -145,6 +152,16 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
std::string last_session_id_;
std::string next_heartbeat_message_;
+ // In order to simulate LoadSession(), CreateSession() and then
+ // UpdateSession() will be called to create a session with known keys.
+ // |session_id_for_emulated_loadsession_| is used to keep track of the
+ // session_id allocated by aes_decryptor, as the session_id will be returned
+ // as |kLoadableWebSessionId|. Future requests for this simulated session
+ // need to use |session_id_for_emulated_loadsession_| for all calls
+ // to aes_decryptor.
+ // |promise_id_for_emulated_loadsession_| is used to keep track of the
+ // original LoadSession() promise, as it is not resolved until the
+ // UpdateSession() call succeeds.
// TODO(xhwang): Extract testing code from main implementation.
// See http://crbug.com/341751
std::string session_id_for_emulated_loadsession_;
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm_common.h b/media/cdm/ppapi/external_clear_key/clear_key_cdm_common.h
index 2bbc5b1..dfd1fe2 100644
--- a/media/cdm/ppapi/external_clear_key/clear_key_cdm_common.h
+++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm_common.h
@@ -10,7 +10,7 @@
namespace media {
// Aliases for the version of the interfaces that this CDM implements.
-typedef cdm::ContentDecryptionModule_5 ClearKeyCdmInterface;
+typedef cdm::ContentDecryptionModule_6 ClearKeyCdmInterface;
typedef ClearKeyCdmInterface::Host ClearKeyCdmHost;
} // namespace media