summaryrefslogtreecommitdiffstats
path: root/media/cdm
diff options
context:
space:
mode:
authorjrummell@chromium.org <jrummell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-30 05:24:47 +0000
committerjrummell@chromium.org <jrummell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-30 05:24:47 +0000
commitda34aa7be7368dc1327a8129b7db0f13b24f5c2b (patch)
tree6340efd5e30735b0bf7352a79dd8e08b54366d6d /media/cdm
parenta6b2aa58719366e64a7fdbde719707304a993a33 (diff)
downloadchromium_src-da34aa7be7368dc1327a8129b7db0f13b24f5c2b.zip
chromium_src-da34aa7be7368dc1327a8129b7db0f13b24f5c2b.tar.gz
chromium_src-da34aa7be7368dc1327a8129b7db0f13b24f5c2b.tar.bz2
Add support for CDM_3.
Changes for CDM_3: - CreateSession() replaces GenerateKeyRequest() - UpdateSession/1 replaces AddKey/2 - ReleaseSession() replaces CancelKeyRequest() - closed event (OnSessionClosed) added. - callbacks renamed (SetSessionId -> OnSessionCreated, SendMessage -> OnSessionMessage, SendReady -> OnSessionReady, SendError -> OnSessionError) Android function names still need to be updated in a separate CL. BUG=224786 TEST=encrypted-media layout tests and browser_tests for encrypted media pass TBR=dmichael Review URL: https://codereview.chromium.org/81803003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@237973 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/cdm')
-rw-r--r--media/cdm/aes_decryptor.cc66
-rw-r--r--media/cdm/aes_decryptor.h38
-rw-r--r--media/cdm/aes_decryptor_unittest.cc110
-rw-r--r--media/cdm/ppapi/cdm_adapter.cc169
-rw-r--r--media/cdm/ppapi/cdm_adapter.h63
-rw-r--r--media/cdm/ppapi/cdm_wrapper.h297
-rw-r--r--media/cdm/ppapi/clear_key_cdm.cc81
-rw-r--r--media/cdm/ppapi/clear_key_cdm.h34
-rw-r--r--media/cdm/ppapi/clear_key_cdm_common.h2
-rw-r--r--media/cdm/ppapi/supported_cdm_versions.h15
10 files changed, 499 insertions, 376 deletions
diff --git a/media/cdm/aes_decryptor.cc b/media/cdm/aes_decryptor.cc
index 10f0499..ee4b987 100644
--- a/media/cdm/aes_decryptor.cc
+++ b/media/cdm/aes_decryptor.cc
@@ -142,23 +142,25 @@ static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input,
return output;
}
-AesDecryptor::AesDecryptor(const KeyAddedCB& key_added_cb,
- const KeyErrorCB& key_error_cb,
- const KeyMessageCB& key_message_cb,
- const SetSessionIdCB& set_session_id_cb)
- : key_added_cb_(key_added_cb),
- key_error_cb_(key_error_cb),
- key_message_cb_(key_message_cb),
- set_session_id_cb_(set_session_id_cb) {}
+AesDecryptor::AesDecryptor(const SessionCreatedCB& session_created_cb,
+ const SessionMessageCB& session_message_cb,
+ const SessionReadyCB& session_ready_cb,
+ const SessionClosedCB& session_closed_cb,
+ const SessionErrorCB& session_error_cb)
+ : session_created_cb_(session_created_cb),
+ session_message_cb_(session_message_cb),
+ session_ready_cb_(session_ready_cb),
+ session_closed_cb_(session_closed_cb),
+ session_error_cb_(session_error_cb) {}
AesDecryptor::~AesDecryptor() {
STLDeleteValues(&key_map_);
}
-bool AesDecryptor::GenerateKeyRequest(uint32 reference_id,
- const std::string& type,
- const uint8* init_data,
- int init_data_length) {
+bool AesDecryptor::CreateSession(uint32 reference_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length) {
std::string session_id_string(base::UintToString(next_session_id_++));
// For now, the AesDecryptor does not care about |type|;
@@ -167,35 +169,28 @@ bool AesDecryptor::GenerateKeyRequest(uint32 reference_id,
if (init_data && init_data_length)
message.assign(init_data, init_data + init_data_length);
- set_session_id_cb_.Run(reference_id, session_id_string);
- key_message_cb_.Run(reference_id, message, std::string());
+ session_created_cb_.Run(reference_id, session_id_string);
+ session_message_cb_.Run(reference_id, message, std::string());
return true;
}
-void AesDecryptor::AddKey(uint32 reference_id,
- const uint8* key,
- int key_length,
- const uint8* init_data,
- int init_data_length) {
- CHECK(key);
- CHECK_GT(key_length, 0);
- DCHECK(!init_data);
- DCHECK_EQ(init_data_length, 0);
-
- // AddKey() is called from update(), where the key(s) are passed as a JSON
- // Web Key (JWK) set. Each JWK needs to be a symmetric key ('kty' = "oct"),
- // with 'kid' being the base64-encoded key id, and 'k' being the
- // base64-encoded key.
- std::string key_string(reinterpret_cast<const char*>(key), key_length);
+void AesDecryptor::UpdateSession(uint32 reference_id,
+ const uint8* response,
+ int response_length) {
+ CHECK(response);
+ CHECK_GT(response_length, 0);
+
+ std::string key_string(reinterpret_cast<const char*>(response),
+ response_length);
KeyIdAndKeyPairs keys;
if (!ExtractKeysFromJWKSet(key_string, &keys)) {
- key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
+ session_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
return;
}
// Make sure that at least one key was extracted.
if (keys.empty()) {
- key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
+ session_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
return;
}
@@ -203,11 +198,11 @@ void AesDecryptor::AddKey(uint32 reference_id,
if (it->second.length() !=
static_cast<size_t>(DecryptConfig::kDecryptionKeySize)) {
DVLOG(1) << "Invalid key length: " << key_string.length();
- key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
+ session_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
return;
}
if (!AddDecryptionKey(it->first, it->second)) {
- key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
+ session_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0);
return;
}
}
@@ -218,10 +213,11 @@ void AesDecryptor::AddKey(uint32 reference_id,
if (!new_video_key_cb_.is_null())
new_video_key_cb_.Run();
- key_added_cb_.Run(reference_id);
+ session_ready_cb_.Run(reference_id);
}
-void AesDecryptor::CancelKeyRequest(uint32 reference_id) {
+void AesDecryptor::ReleaseSession(uint32 reference_id) {
+ // TODO: Implement: http://crbug.com/313412.
}
Decryptor* AesDecryptor::GetDecryptor() {
diff --git a/media/cdm/aes_decryptor.h b/media/cdm/aes_decryptor.h
index d1f9341..8e03106 100644
--- a/media/cdm/aes_decryptor.h
+++ b/media/cdm/aes_decryptor.h
@@ -27,23 +27,22 @@ namespace media {
// encryption must be CTR with a key size of 128bits.
class MEDIA_EXPORT AesDecryptor : public MediaKeys, public Decryptor {
public:
- AesDecryptor(const KeyAddedCB& key_added_cb,
- const KeyErrorCB& key_error_cb,
- const KeyMessageCB& key_message_cb,
- const SetSessionIdCB& set_session_id_cb);
+ AesDecryptor(const SessionCreatedCB& session_created_cb,
+ const SessionMessageCB& session_message_cb,
+ const SessionReadyCB& session_ready_cb,
+ const SessionClosedCB& session_closed_cb,
+ const SessionErrorCB& session_error_cb);
virtual ~AesDecryptor();
// MediaKeys implementation.
- virtual bool GenerateKeyRequest(uint32 reference_id,
- const std::string& type,
- const uint8* init_data,
- int init_data_length) OVERRIDE;
- virtual void AddKey(uint32 reference_id,
- const uint8* key,
- int key_length,
- const uint8* init_data,
- int init_data_length) OVERRIDE;
- virtual void CancelKeyRequest(uint32 reference_id) OVERRIDE;
+ virtual bool CreateSession(uint32 reference_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length) OVERRIDE;
+ virtual void UpdateSession(uint32 reference_id,
+ const uint8* response,
+ int response_length) OVERRIDE;
+ virtual void ReleaseSession(uint32 reference_id) OVERRIDE;
virtual Decryptor* GetDecryptor() OVERRIDE;
// Decryptor implementation.
@@ -99,11 +98,12 @@ class MEDIA_EXPORT AesDecryptor : public MediaKeys, public Decryptor {
// the key. Returns NULL if no key is associated with |key_id|.
DecryptionKey* GetKey(const std::string& key_id) const;
- // Callbacks for firing key events.
- KeyAddedCB key_added_cb_;
- KeyErrorCB key_error_cb_;
- KeyMessageCB key_message_cb_;
- SetSessionIdCB set_session_id_cb_;
+ // Callbacks for firing session events.
+ SessionCreatedCB session_created_cb_;
+ SessionMessageCB session_message_cb_;
+ SessionReadyCB session_ready_cb_;
+ SessionClosedCB session_closed_cb_;
+ SessionErrorCB session_error_cb_;
// KeyMap owns the DecryptionKey* and must delete them when they are
// not needed any more.
diff --git a/media/cdm/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc
index d9730a2..cd0d460 100644
--- a/media/cdm/aes_decryptor_unittest.cc
+++ b/media/cdm/aes_decryptor_unittest.cc
@@ -185,11 +185,16 @@ static scoped_refptr<DecoderBuffer> CreateEncryptedBuffer(
class AesDecryptorTest : public testing::Test {
public:
AesDecryptorTest()
- : decryptor_(
- base::Bind(&AesDecryptorTest::KeyAdded, base::Unretained(this)),
- base::Bind(&AesDecryptorTest::KeyError, base::Unretained(this)),
- base::Bind(&AesDecryptorTest::KeyMessage, base::Unretained(this)),
- base::Bind(&AesDecryptorTest::SetSession, base::Unretained(this))),
+ : decryptor_(base::Bind(&AesDecryptorTest::OnSessionCreated,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionMessage,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionReady,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionClosed,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionError,
+ base::Unretained(this))),
reference_id_(MediaKeys::kInvalidReferenceId),
decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted,
base::Unretained(this))),
@@ -207,12 +212,12 @@ class AesDecryptorTest : public testing::Test {
}
protected:
- void GenerateKeyRequest(const std::vector<uint8>& key_id) {
+ void CreateSession(const std::vector<uint8>& key_id) {
reference_id_ = 6;
DCHECK(!key_id.empty());
- EXPECT_CALL(*this, SetSession(reference_id_, StrNe(std::string())));
- EXPECT_CALL(*this, KeyMessage(reference_id_, key_id, ""));
- EXPECT_TRUE(decryptor_.GenerateKeyRequest(
+ EXPECT_CALL(*this, OnSessionCreated(reference_id_, StrNe(std::string())));
+ EXPECT_CALL(*this, OnSessionMessage(reference_id_, key_id, ""));
+ EXPECT_TRUE(decryptor_.CreateSession(
reference_id_, std::string(), &key_id[0], key_id.size()));
}
@@ -225,18 +230,17 @@ class AesDecryptorTest : public testing::Test {
DCHECK(!key.empty());
if (result == KEY_ADDED) {
- EXPECT_CALL(*this, KeyAdded(reference_id_));
+ EXPECT_CALL(*this, OnSessionReady(reference_id_));
} else if (result == KEY_ERROR) {
- EXPECT_CALL(*this, KeyError(reference_id_, MediaKeys::kUnknownError, 0));
+ EXPECT_CALL(*this,
+ OnSessionError(reference_id_, MediaKeys::kUnknownError, 0));
} else {
NOTREACHED();
}
- decryptor_.AddKey(reference_id_,
- reinterpret_cast<const uint8*>(key.c_str()),
- key.length(),
- NULL,
- 0);
+ decryptor_.UpdateSession(reference_id_,
+ reinterpret_cast<const uint8*>(key.c_str()),
+ key.length());
}
MOCK_METHOD2(BufferDecrypted, void(Decryptor::Status,
@@ -287,14 +291,16 @@ class AesDecryptorTest : public testing::Test {
}
}
- MOCK_METHOD1(KeyAdded, void(uint32 reference_id));
- MOCK_METHOD3(KeyError, void(uint32 reference_id, MediaKeys::KeyError, int));
- MOCK_METHOD3(KeyMessage,
+ MOCK_METHOD2(OnSessionCreated,
+ void(uint32 reference_id, const std::string& session_id));
+ MOCK_METHOD3(OnSessionMessage,
void(uint32 reference_id,
const std::vector<uint8>& message,
const std::string& default_url));
- MOCK_METHOD2(SetSession,
- void(uint32 reference_id, const std::string& session_id));
+ MOCK_METHOD1(OnSessionReady, void(uint32 reference_id));
+ MOCK_METHOD1(OnSessionClosed, void(uint32 reference_id));
+ MOCK_METHOD3(OnSessionError,
+ void(uint32 reference_id, MediaKeys::KeyError, int system_code));
AesDecryptor decryptor_;
uint32 reference_id_;
@@ -310,36 +316,32 @@ class AesDecryptorTest : public testing::Test {
const std::vector<SubsampleEntry> no_subsample_entries_;
};
-TEST_F(AesDecryptorTest, GenerateKeyRequestWithNullInitData) {
+TEST_F(AesDecryptorTest, CreateSessionWithNullInitData) {
reference_id_ = 8;
- EXPECT_CALL(*this, KeyMessage(reference_id_, IsEmpty(), ""));
- EXPECT_CALL(*this, SetSession(reference_id_, StrNe(std::string())));
- EXPECT_TRUE(
- decryptor_.GenerateKeyRequest(reference_id_, std::string(), NULL, 0));
+ EXPECT_CALL(*this, OnSessionMessage(reference_id_, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(reference_id_, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(reference_id_, std::string(), NULL, 0));
}
-TEST_F(AesDecryptorTest, MultipleGenerateKeyRequest) {
+TEST_F(AesDecryptorTest, MultipleCreateSession) {
uint32 reference_id1 = 10;
- EXPECT_CALL(*this, KeyMessage(reference_id1, IsEmpty(), ""));
- EXPECT_CALL(*this, SetSession(reference_id1, StrNe(std::string())));
- EXPECT_TRUE(
- decryptor_.GenerateKeyRequest(reference_id1, std::string(), NULL, 0));
+ EXPECT_CALL(*this, OnSessionMessage(reference_id1, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(reference_id1, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(reference_id1, std::string(), NULL, 0));
uint32 reference_id2 = 11;
- EXPECT_CALL(*this, KeyMessage(reference_id2, IsEmpty(), ""));
- EXPECT_CALL(*this, SetSession(reference_id2, StrNe(std::string())));
- EXPECT_TRUE(
- decryptor_.GenerateKeyRequest(reference_id2, std::string(), NULL, 0));
+ EXPECT_CALL(*this, OnSessionMessage(reference_id2, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(reference_id2, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(reference_id2, std::string(), NULL, 0));
uint32 reference_id3 = 23;
- EXPECT_CALL(*this, KeyMessage(reference_id3, IsEmpty(), ""));
- EXPECT_CALL(*this, SetSession(reference_id3, StrNe(std::string())));
- EXPECT_TRUE(
- decryptor_.GenerateKeyRequest(reference_id3, std::string(), NULL, 0));
+ EXPECT_CALL(*this, OnSessionMessage(reference_id3, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(reference_id3, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(reference_id3, std::string(), NULL, 0));
}
TEST_F(AesDecryptorTest, NormalDecryption) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
@@ -347,7 +349,7 @@ TEST_F(AesDecryptorTest, NormalDecryption) {
}
TEST_F(AesDecryptorTest, DecryptionWithOffset) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 23, no_subsample_entries_);
@@ -362,7 +364,7 @@ TEST_F(AesDecryptorTest, UnencryptedFrame) {
}
TEST_F(AesDecryptorTest, WrongKey) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kWrongKeyAsJWK, KEY_ADDED);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
@@ -377,7 +379,7 @@ TEST_F(AesDecryptorTest, NoKey) {
}
TEST_F(AesDecryptorTest, KeyReplacement) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
@@ -391,12 +393,12 @@ TEST_F(AesDecryptorTest, KeyReplacement) {
}
TEST_F(AesDecryptorTest, WrongSizedKey) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kWrongSizedKeyAsJWK, KEY_ERROR);
}
TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 10, no_subsample_entries_);
@@ -425,7 +427,7 @@ TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
}
TEST_F(AesDecryptorTest, CorruptedIv) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
std::vector<uint8> bad_iv = iv_;
@@ -438,7 +440,7 @@ TEST_F(AesDecryptorTest, CorruptedIv) {
}
TEST_F(AesDecryptorTest, CorruptedData) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
std::vector<uint8> bad_data = encrypted_data_;
@@ -450,7 +452,7 @@ TEST_F(AesDecryptorTest, CorruptedData) {
}
TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, std::vector<uint8>(), 0, no_subsample_entries_);
@@ -458,7 +460,7 @@ TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
}
TEST_F(AesDecryptorTest, SubsampleDecryption) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
subsample_encrypted_data_, key_id_, iv_, 0, normal_subsample_entries_);
@@ -469,7 +471,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryption) {
// expect to encounter this in the wild, but since the DecryptConfig doesn't
// disallow such a configuration, it should be covered.
TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
subsample_encrypted_data_, key_id_, iv_, 23, normal_subsample_entries_);
@@ -477,7 +479,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
}
TEST_F(AesDecryptorTest, SubsampleWrongSize) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
std::vector<SubsampleEntry> subsample_entries_wrong_size(
@@ -490,7 +492,7 @@ TEST_F(AesDecryptorTest, SubsampleWrongSize) {
}
TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
std::vector<SubsampleEntry> subsample_entries_invalid_total_size(
@@ -506,7 +508,7 @@ TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
// No cypher bytes in any of the subsamples.
TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
std::vector<SubsampleEntry> clear_only_subsample_entries(
@@ -520,7 +522,7 @@ TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
// No clear bytes in any of the subsamples.
TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) {
- GenerateKeyRequest(key_id_);
+ CreateSession(key_id_);
AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
std::vector<SubsampleEntry> cypher_only_subsample_entries(
diff --git a/media/cdm/ppapi/cdm_adapter.cc b/media/cdm/ppapi/cdm_adapter.cc
index 1d9200a..489eb1d 100644
--- a/media/cdm/ppapi/cdm_adapter.cc
+++ b/media/cdm/ppapi/cdm_adapter.cc
@@ -235,7 +235,7 @@ bool CdmAdapter::CreateCdmInstance(const std::string& key_system) {
// No KeyErrors should be reported in this function because they cannot be
// bubbled up in the WD EME API. Those errors will be reported during session
-// creation (aka GenerateKeyRequest).
+// creation (CreateSession).
void CdmAdapter::Initialize(const std::string& key_system) {
PP_DCHECK(!key_system.empty());
PP_DCHECK(key_system_.empty() || (key_system_ == key_system && cdm_));
@@ -247,13 +247,13 @@ void CdmAdapter::Initialize(const std::string& key_system) {
key_system_ = key_system;
}
-void CdmAdapter::GenerateKeyRequest(uint32_t reference_id,
- const std::string& type,
- pp::VarArrayBuffer init_data) {
- // Initialize() doesn't report an error, so GenerateKeyRequest() can be called
+void CdmAdapter::CreateSession(uint32_t reference_id,
+ const std::string& type,
+ pp::VarArrayBuffer init_data) {
+ // Initialize() doesn't report an error, so CreateSession() can be called
// even if Initialize() failed.
if (!cdm_) {
- SendUnknownKeyError(reference_id);
+ OnSessionError(reference_id, cdm::kUnknownError, 0);
return;
}
@@ -261,7 +261,7 @@ void CdmAdapter::GenerateKeyRequest(uint32_t reference_id,
PP_URLComponents_Dev url_components = {};
const pp::URLUtil_Dev* url_util = pp::URLUtil_Dev::Get();
if (!url_util) {
- SendUnknownKeyError(reference_id);
+ OnSessionError(reference_id, cdm::kUnknownError, 0);
return;
}
pp::Var href = url_util->GetDocumentURL(
@@ -272,56 +272,52 @@ void CdmAdapter::GenerateKeyRequest(uint32_t reference_id,
PP_DCHECK(0 < url_components.host.len);
#endif // defined(CHECK_DOCUMENT_URL)
- cdm_->GenerateKeyRequest(reference_id,
- type.data(),
- type.size(),
- static_cast<const uint8_t*>(init_data.Map()),
- init_data.ByteLength());
+ cdm_->CreateSession(reference_id,
+ type.data(),
+ type.size(),
+ static_cast<const uint8_t*>(init_data.Map()),
+ init_data.ByteLength());
}
-void CdmAdapter::AddKey(uint32_t reference_id,
- pp::VarArrayBuffer key,
- pp::VarArrayBuffer init_data) {
+void CdmAdapter::UpdateSession(uint32_t reference_id,
+ pp::VarArrayBuffer response) {
// TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
// We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
if (!cdm_) {
- SendUnknownKeyError(reference_id);
+ OnSessionError(reference_id, cdm::kUnknownError, 0);
return;
}
- const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map());
- const uint32_t key_size = key.ByteLength();
- const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map());
- const uint32_t init_data_size = init_data.ByteLength();
- PP_DCHECK(!init_data_ptr == !init_data_size);
+ const uint8_t* response_ptr = static_cast<const uint8_t*>(response.Map());
+ const uint32_t response_size = response.ByteLength();
- if (!key_ptr || key_size <= 0) {
- SendUnknownKeyError(reference_id);
+ if (!response_ptr || response_size <= 0) {
+ OnSessionError(reference_id, cdm::kUnknownError, 0);
return;
}
- CdmWrapper::Result result = cdm_->AddKey(
- reference_id, key_ptr, key_size, init_data_ptr, init_data_size);
+ CdmWrapper::Result result =
+ cdm_->UpdateSession(reference_id, response_ptr, response_size);
switch (result) {
case CdmWrapper::NO_ACTION:
break;
case CdmWrapper::CALL_KEY_ADDED:
- SendKeyAdded(reference_id);
+ OnSessionReady(reference_id);
break;
case CdmWrapper::CALL_KEY_ERROR:
- SendUnknownKeyError(reference_id);
+ OnSessionError(reference_id, cdm::kUnknownError, 0);
break;
}
}
-void CdmAdapter::CancelKeyRequest(uint32_t reference_id) {
+void CdmAdapter::ReleaseSession(uint32_t reference_id) {
// TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
// We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
if (!cdm_) {
- SendUnknownKeyError(reference_id);
+ OnSessionError(reference_id, cdm::kUnknownError, 0);
return;
}
- CdmWrapper::Result result = cdm_->CancelKeyRequest(reference_id);
+ CdmWrapper::Result result = cdm_->ReleaseSession(reference_id);
switch (result) {
case CdmWrapper::NO_ACTION:
break;
@@ -329,7 +325,7 @@ void CdmAdapter::CancelKeyRequest(uint32_t reference_id) {
PP_NOTREACHED();
break;
case CdmWrapper::CALL_KEY_ERROR:
- SendUnknownKeyError(reference_id);
+ OnSessionError(reference_id, cdm::kUnknownError, 0);
break;
}
}
@@ -542,14 +538,9 @@ void CdmAdapter::SendKeyMessage(
PP_DCHECK(!session_id_str.empty());
uint32_t reference_id = cdm_->DetermineReferenceId(session_id_str);
- PostOnMain(callback_factory_.NewCallback(
- &CdmAdapter::SetSessionId, reference_id, session_id_str));
-
- PostOnMain(callback_factory_.NewCallback(
- &CdmAdapter::KeyMessage,
- reference_id,
- std::vector<uint8>(message, message + message_length),
- std::string(default_url, default_url_length)));
+ OnSessionCreated(reference_id, session_id, session_id_length);
+ OnSessionMessage(
+ reference_id, message, message_length, default_url, default_url_length);
}
void CdmAdapter::SendKeyError(const char* session_id,
@@ -558,8 +549,7 @@ void CdmAdapter::SendKeyError(const char* session_id,
uint32_t system_code) {
std::string session_id_str(session_id, session_id_length);
uint32_t reference_id = cdm_->DetermineReferenceId(session_id_str);
-
- SendKeyErrorInternal(reference_id, error_code, system_code);
+ OnSessionError(reference_id, error_code, system_code);
}
void CdmAdapter::GetPrivateData(int32_t* instance,
@@ -568,31 +558,58 @@ void CdmAdapter::GetPrivateData(int32_t* instance,
*get_interface = pp::Module::Get()->get_browser_interface();
}
-void CdmAdapter::SendUnknownKeyError(uint32_t reference_id) {
- SendKeyErrorInternal(reference_id, cdm::kUnknownError, 0);
+void CdmAdapter::OnSessionCreated(uint32_t reference_id,
+ const char* session_id,
+ uint32_t session_id_length) {
+ PostOnMain(callback_factory_.NewCallback(
+ &CdmAdapter::SendSessionCreatedInternal,
+ reference_id,
+ std::string(session_id, session_id_length)));
+}
+
+void CdmAdapter::OnSessionMessage(uint32_t reference_id,
+ const char* message,
+ uint32_t message_length,
+ const char* destination_url,
+ uint32_t destination_url_length) {
+ PostOnMain(callback_factory_.NewCallback(
+ &CdmAdapter::SendSessionMessageInternal,
+ reference_id,
+ std::vector<uint8>(message, message + message_length),
+ std::string(destination_url, destination_url_length)));
+}
+
+void CdmAdapter::OnSessionReady(uint32_t reference_id) {
+ PostOnMain(callback_factory_.NewCallback(
+ &CdmAdapter::SendSessionReadyInternal, reference_id));
}
-void CdmAdapter::SendKeyAdded(uint32_t reference_id) {
- PostOnMain(
- callback_factory_.NewCallback(&CdmAdapter::KeyAdded, reference_id));
+void CdmAdapter::OnSessionClosed(uint32_t reference_id) {
+ PostOnMain(callback_factory_.NewCallback(
+ &CdmAdapter::SendSessionClosedInternal, reference_id));
}
-void CdmAdapter::SendKeyErrorInternal(uint32_t reference_id,
- cdm::MediaKeyError error_code,
- uint32_t system_code) {
+void CdmAdapter::OnSessionError(uint32_t reference_id,
+ cdm::MediaKeyError error_code,
+ uint32_t system_code) {
PostOnMain(callback_factory_.NewCallback(
- &CdmAdapter::KeyError, reference_id, error_code, system_code));
+ &CdmAdapter::SendSessionErrorInternal,
+ reference_id,
+ error_code,
+ system_code));
}
-void CdmAdapter::KeyAdded(int32_t result, uint32_t reference_id) {
+void CdmAdapter::SendSessionCreatedInternal(int32_t result,
+ uint32_t reference_id,
+ const std::string& session_id) {
PP_DCHECK(result == PP_OK);
- pp::ContentDecryptor_Private::KeyAdded(reference_id);
+ pp::ContentDecryptor_Private::SessionCreated(reference_id, session_id);
}
-void CdmAdapter::KeyMessage(int32_t result,
- uint32_t reference_id,
- const std::vector<uint8>& message,
- const std::string& default_url) {
+void CdmAdapter::SendSessionMessageInternal(int32_t result,
+ uint32_t reference_id,
+ const std::vector<uint8>& message,
+ const std::string& default_url) {
PP_DCHECK(result == PP_OK);
pp::VarArrayBuffer message_array_buffer(message.size());
@@ -600,25 +617,29 @@ void CdmAdapter::KeyMessage(int32_t result,
memcpy(message_array_buffer.Map(), message.data(), message.size());
}
- pp::ContentDecryptor_Private::KeyMessage(
- reference_id,
- message_array_buffer,
- default_url);
+ pp::ContentDecryptor_Private::SessionMessage(
+ reference_id, message_array_buffer, default_url);
+}
+
+void CdmAdapter::SendSessionReadyInternal(int32_t result,
+ uint32_t reference_id) {
+ PP_DCHECK(result == PP_OK);
+ pp::ContentDecryptor_Private::SessionReady(reference_id);
}
-void CdmAdapter::KeyError(int32_t result,
- uint32_t reference_id,
- cdm::MediaKeyError error_code,
- uint32_t system_code) {
+void CdmAdapter::SendSessionClosedInternal(int32_t result,
+ uint32_t reference_id) {
PP_DCHECK(result == PP_OK);
- pp::ContentDecryptor_Private::KeyError(reference_id, error_code, system_code);
+ pp::ContentDecryptor_Private::SessionClosed(reference_id);
}
-void CdmAdapter::SetSessionId(int32_t result,
- uint32_t reference_id,
- const std::string& session_id) {
+void CdmAdapter::SendSessionErrorInternal(int32_t result,
+ uint32_t reference_id,
+ cdm::MediaKeyError error_code,
+ uint32_t system_code) {
PP_DCHECK(result == PP_OK);
- pp::ContentDecryptor_Private::SetSessionId(reference_id, session_id);
+ pp::ContentDecryptor_Private::SessionError(
+ reference_id, error_code, system_code);
}
void CdmAdapter::DeliverBlock(int32_t result,
@@ -928,7 +949,7 @@ void* GetCdmHost(int host_interface_version, void* user_data) {
return NULL;
COMPILE_ASSERT(cdm::ContentDecryptionModule::Host::kVersion ==
- cdm::ContentDecryptionModule_2::Host::kVersion,
+ cdm::ContentDecryptionModule_3::Host::kVersion,
update_code_below);
// Ensure IsSupportedCdmHostVersion matches implementation of this function.
@@ -949,10 +970,10 @@ void* GetCdmHost(int host_interface_version, void* user_data) {
CdmAdapter* cdm_adapter = static_cast<CdmAdapter*>(user_data);
switch (host_interface_version) {
- // The latest CDM host version.
- case cdm::ContentDecryptionModule::Host::kVersion:
- return static_cast<cdm::ContentDecryptionModule::Host*>(cdm_adapter);
- // Older supported version(s) of the CDM host.
+ case cdm::Host_3::kVersion:
+ return static_cast<cdm::Host_3*>(cdm_adapter);
+ case cdm::Host_2::kVersion:
+ return static_cast<cdm::Host_2*>(cdm_adapter);
case cdm::Host_1::kVersion:
return static_cast<cdm::Host_1*>(cdm_adapter);
default:
diff --git a/media/cdm/ppapi/cdm_adapter.h b/media/cdm/ppapi/cdm_adapter.h
index 0542c5d..57e7524 100644
--- a/media/cdm/ppapi/cdm_adapter.h
+++ b/media/cdm/ppapi/cdm_adapter.h
@@ -38,7 +38,8 @@ void* GetCdmHost(int host_interface_version, void* user_data);
class CdmAdapter : public pp::Instance,
public pp::ContentDecryptor_Private,
public cdm::Host_1,
- public cdm::Host_2 {
+ public cdm::Host_2,
+ public cdm::Host_3 {
public:
CdmAdapter(PP_Instance instance, pp::Module* module);
virtual ~CdmAdapter();
@@ -52,13 +53,12 @@ class CdmAdapter : public pp::Instance,
// Note: Results of calls to these methods must be reported through the
// PPB_ContentDecryptor_Private interface.
virtual void Initialize(const std::string& key_system) OVERRIDE;
- virtual void GenerateKeyRequest(uint32_t reference_id,
- const std::string& type,
- pp::VarArrayBuffer init_data) OVERRIDE;
- virtual void AddKey(uint32_t reference_id,
- pp::VarArrayBuffer key,
- pp::VarArrayBuffer init_data) OVERRIDE;
- virtual void CancelKeyRequest(uint32_t reference_id) OVERRIDE;
+ virtual void CreateSession(uint32_t reference_id,
+ const std::string& type,
+ pp::VarArrayBuffer init_data) OVERRIDE;
+ virtual void UpdateSession(uint32_t reference_id,
+ pp::VarArrayBuffer response) OVERRIDE;
+ virtual void ReleaseSession(uint32_t reference_id) OVERRIDE;
virtual void Decrypt(
pp::Buffer_Dev encrypted_buffer,
const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
@@ -103,6 +103,21 @@ class CdmAdapter : public pp::Instance,
cdm::StreamType stream_type,
cdm::Status decoder_status) OVERRIDE;
+ // cdm::Host_3 implementation.
+ virtual void OnSessionCreated(uint32_t reference_id,
+ const char* session_id,
+ uint32_t session_id_length) OVERRIDE;
+ virtual void OnSessionMessage(uint32_t reference_id,
+ const char* message,
+ uint32_t message_length,
+ const char* destination_url,
+ uint32_t destination_url_length) OVERRIDE;
+ virtual void OnSessionReady(uint32_t reference_id) OVERRIDE;
+ virtual void OnSessionClosed(uint32_t reference_id) OVERRIDE;
+ virtual void OnSessionError(uint32_t reference_id,
+ cdm::MediaKeyError error_code,
+ uint32_t system_code) OVERRIDE;
+
private:
typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
@@ -110,27 +125,23 @@ class CdmAdapter : public pp::Instance,
bool CreateCdmInstance(const std::string& key_system);
- void SendUnknownKeyError(uint32_t reference_id);
- void SendKeyAdded(uint32_t reference_id);
- void SendKeyErrorInternal(uint32_t reference_id,
- cdm::MediaKeyError error_code,
- uint32_t system_code);
-
// <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
// <code>callback_factory_</code> to ensure that calls into
// <code>PPP_ContentDecryptor_Private</code> are asynchronous.
- void KeyAdded(int32_t result, uint32_t reference_id);
- void KeyMessage(int32_t result,
- uint32_t reference_id,
- const std::vector<uint8>& message,
- const std::string& default_url);
- void KeyError(int32_t result,
- uint32_t reference_id,
- cdm::MediaKeyError error_code,
- uint32_t system_code);
- void SetSessionId(int32_t result,
- uint32_t reference_id,
- const std::string& session_id);
+ void SendSessionCreatedInternal(int32_t result,
+ uint32_t reference_id,
+ const std::string& session_id);
+ void SendSessionMessageInternal(int32_t result,
+ uint32_t reference_id,
+ const std::vector<uint8>& message,
+ const std::string& default_url);
+ void SendSessionReadyInternal(int32_t result, uint32_t reference_id);
+ void SendSessionClosedInternal(int32_t result, uint32_t reference_id);
+ void SendSessionErrorInternal(int32_t result,
+ uint32_t reference_id,
+ cdm::MediaKeyError error_code,
+ uint32_t system_code);
+
void DeliverBlock(int32_t result,
const cdm::Status& status,
const LinkedDecryptedBlock& decrypted_block,
diff --git a/media/cdm/ppapi/cdm_wrapper.h b/media/cdm/ppapi/cdm_wrapper.h
index 8d3003a..63d8bbf 100644
--- a/media/cdm/ppapi/cdm_wrapper.h
+++ b/media/cdm/ppapi/cdm_wrapper.h
@@ -52,17 +52,15 @@ class CdmWrapper {
virtual ~CdmWrapper() {};
- virtual void GenerateKeyRequest(uint32_t reference_id,
- const char* type,
- uint32_t type_size,
- const uint8_t* init_data,
- uint32_t init_data_size) = 0;
- virtual Result AddKey(uint32_t reference_id,
- const uint8_t* key,
- uint32_t key_size,
- const uint8_t* key_id,
- uint32_t key_id_size) = 0;
- virtual Result CancelKeyRequest(uint32_t reference_id) = 0;
+ virtual void CreateSession(uint32_t reference_id,
+ const char* type,
+ uint32_t type_size,
+ const uint8_t* init_data,
+ uint32_t init_data_size) = 0;
+ virtual Result UpdateSession(uint32_t reference_id,
+ const uint8_t* response,
+ uint32_t response_size) = 0;
+ virtual Result ReleaseSession(uint32_t reference_id) = 0;
virtual void TimerExpired(void* context) = 0;
virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
cdm::DecryptedBlock* decrypted_buffer) = 0;
@@ -85,10 +83,11 @@ class CdmWrapper {
uint32_t output_protection_mask) = 0;
// ContentDecryptionModule_1 and ContentDecryptionModule_2 interface methods
- // AddKey() and CancelKeyRequest() (older versions of Update() and Close(),
- // respectively) pass in the session_id rather than the reference_id. As well,
- // Host_1 and Host_2 callbacks SendKeyMessage() and SendKeyError() include the
- // session ID, but the actual callbacks need the reference ID.
+ // AddKey() and CancelKeyRequest() (older versions of UpdateSession() and
+ // ReleaseSession(), respectively) pass in the session_id rather than the
+ // reference_id. As well, Host_1 and Host_2 callbacks SendKeyMessage() and
+ // SendKeyError() include the session ID, but the actual callbacks need the
+ // reference ID.
//
// The following functions maintain the reference_id <-> session_id mapping.
// These can be removed once _1 and _2 interfaces are no longer supported.
@@ -99,16 +98,15 @@ class CdmWrapper {
// Determine the corresponding session_id for |reference_id|.
virtual const std::string LookupSessionId(uint32_t reference_id) = 0;
- protected:
+ // TODO(jrummell): The following can be removed once CDM_1 and CDM_2 are
+ // no longer supported.
typedef std::map<uint32_t, std::string> SessionMap;
static const uint32_t kInvalidReferenceId = 0;
- CdmWrapper() : current_key_request_reference_id_(kInvalidReferenceId) {}
-
// Map between session_id and reference_id.
SessionMap session_map_;
- // As the response from GenerateKeyRequest() may be synchronous or
+ // As the response from PrefixedGenerateKeyRequest() may be synchronous or
// asynchronous, keep track of the current request during the call to handle
// synchronous responses or errors. If no response received, add this request
// to a queue and assume that the subsequent responses come back in the order
@@ -118,6 +116,9 @@ class CdmWrapper {
uint32_t current_key_request_reference_id_;
std::queue<uint32_t> pending_key_request_reference_ids_;
+ protected:
+ CdmWrapper() : current_key_request_reference_id_(kInvalidReferenceId) {}
+
private:
DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
};
@@ -146,91 +147,24 @@ class CdmWrapperImpl : public CdmWrapper {
cdm_->Destroy();
}
- // TODO(jrummell): In CDM_3 all key callbacks will use reference_id, so there
- // is no need to keep track of the current/pending request IDs. As well, the
- // definition for AddKey() and CancelKeyRequest() require the CDM to always
- // send a response (success or error), so the callbacks are not required.
- // Simplify the following 3 routines when CDM_3 is supported.
-
- virtual void GenerateKeyRequest(uint32_t reference_id,
- const char* type,
- uint32_t type_size,
- const uint8_t* init_data,
- uint32_t init_data_size) OVERRIDE {
- // As it is possible for CDMs to reply synchronously during the call to
- // GenerateKeyRequest(), keep track of |reference_id|.
- current_key_request_reference_id_ = reference_id;
-
- cdm::Status status =
- cdm_->GenerateKeyRequest(type, type_size, init_data, init_data_size);
- PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
- if (status != cdm::kSuccess) {
- // If GenerateKeyRequest() failed, no subsequent asynchronous replies
- // will be sent. Verify that a response was sent synchronously.
- PP_DCHECK(current_key_request_reference_id_ == kInvalidReferenceId);
- current_key_request_reference_id_ = kInvalidReferenceId;
- return;
- }
-
- if (current_key_request_reference_id_) {
- // If this request is still pending (SendKeyMessage() or SendKeyError()
- // not called synchronously), add |reference_id| to the end of the queue.
- // Without CDM support, it is impossible to match SendKeyMessage()
- // (or SendKeyError()) responses to the |reference_id|. Doing the best
- // we can by keeping track of this in a queue, and assuming the responses
- // come back in order.
- pending_key_request_reference_ids_.push(reference_id);
- current_key_request_reference_id_ = kInvalidReferenceId;
- }
+ virtual void CreateSession(uint32_t reference_id,
+ const char* type,
+ uint32_t type_size,
+ const uint8_t* init_data,
+ uint32_t init_data_size) OVERRIDE {
+ cdm_->CreateSession(
+ reference_id, type, type_size, init_data, init_data_size);
}
- virtual Result AddKey(uint32_t reference_id,
- const uint8_t* key,
- uint32_t key_size,
- const uint8_t* key_id,
- uint32_t key_id_size) OVERRIDE {
- const std::string session_id = LookupSessionId(reference_id);
- if (session_id.empty()) {
- // Possible if AddKey() called before GenerateKeyRequest().
- return CALL_KEY_ERROR;
- }
-
- cdm::Status status = cdm_->AddKey(session_id.data(),
- session_id.size(),
- key,
- key_size,
- key_id,
- key_id_size);
- PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
- if (status != cdm::kSuccess) {
- // http://crbug.com/310345: CDMs should send a KeyError message if they
- // return a failure, so no need to do it twice. Remove this once all CDMs
- // have been updated.
- return CALL_KEY_ERROR;
- }
-
- return CALL_KEY_ADDED;
+ virtual Result UpdateSession(uint32_t reference_id,
+ const uint8_t* response,
+ uint32_t response_size) OVERRIDE {
+ cdm_->UpdateSession(reference_id, response, response_size);
+ return NO_ACTION;
}
- virtual Result CancelKeyRequest(uint32_t reference_id) OVERRIDE {
- const std::string session_id = LookupSessionId(reference_id);
- if (session_id.empty()) {
- // Possible if CancelKeyRequest() called before GenerateKeyRequest().
- return CALL_KEY_ERROR;
- }
-
- session_map_.erase(reference_id);
- cdm::Status status =
- cdm_->CancelKeyRequest(session_id.data(), session_id.size());
-
- PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
- if (status != cdm::kSuccess) {
- // http://crbug.com/310345: CDMs should send a KeyError message if they
- // return a failure, so no need to do it twice. Remove this once all CDMs
- // have been updated.
- return CALL_KEY_ERROR;
- }
-
+ virtual Result ReleaseSession(uint32_t reference_id) OVERRIDE {
+ cdm_->ReleaseSession(reference_id);
return NO_ACTION;
}
@@ -293,11 +227,12 @@ class CdmWrapperImpl : public CdmWrapper {
}
// There is no entry in the map; assume it came from the current
- // GenerateKeyRequest() call (if possible). If no current request,
- // assume it came from the oldest GenerateKeyRequest() call.
+ // PrefixedGenerateKeyRequest() call (if possible). If no current request,
+ // assume it came from the oldest PrefixedGenerateKeyRequest() call.
uint32_t reference_id = current_key_request_reference_id_;
if (current_key_request_reference_id_) {
- // Only 1 response is allowed for the current GenerateKeyRequest().
+ // Only 1 response is allowed for the current
+ // PrefixedGenerateKeyRequest().
current_key_request_reference_id_ = kInvalidReferenceId;
} else {
PP_DCHECK(!pending_key_request_reference_ids_.empty());
@@ -318,7 +253,7 @@ class CdmWrapperImpl : public CdmWrapper {
}
const std::string LookupSessionId(uint32_t reference_id) {
- // Session may not exist if error happens during GenerateKeyRequest().
+ // Session may not exist if error happens during CreateSession().
SessionMap::iterator it = session_map_.find(reference_id);
return (it != session_map_.end()) ? it->second : std::string();
}
@@ -333,8 +268,124 @@ class CdmWrapperImpl : public CdmWrapper {
DISALLOW_COPY_AND_ASSIGN(CdmWrapperImpl);
};
+// For ContentDecryptionModule_1 and ContentDecryptionModule_2,
+// CreateSession(), UpdateSession(), and ReleaseSession() call methods
+// are incompatible with ContentDecryptionModule_3. Use the following
+// templated functions to handle this.
+
+template <class CdmInterface>
+void PrefixedGenerateKeyRequest(CdmWrapper* wrapper,
+ CdmInterface* cdm,
+ uint32_t reference_id,
+ const char* type,
+ uint32_t type_size,
+ const uint8_t* init_data,
+ uint32_t init_data_size) {
+ // As it is possible for CDMs to reply synchronously during the call to
+ // GenerateKeyRequest(), keep track of |reference_id|.
+ wrapper->current_key_request_reference_id_ = reference_id;
+
+ cdm::Status status =
+ cdm->GenerateKeyRequest(type, type_size, init_data, init_data_size);
+ PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
+ if (status != cdm::kSuccess) {
+ // If GenerateKeyRequest() failed, no subsequent asynchronous replies
+ // will be sent. Verify that a response was sent synchronously.
+ PP_DCHECK(wrapper->current_key_request_reference_id_ ==
+ CdmWrapper::kInvalidReferenceId);
+ wrapper->current_key_request_reference_id_ =
+ CdmWrapper::kInvalidReferenceId;
+ return;
+ }
+
+ if (wrapper->current_key_request_reference_id_) {
+ // If this request is still pending (SendKeyMessage() or SendKeyError()
+ // not called synchronously), add |reference_id| to the end of the queue.
+ // Without CDM support, it is impossible to match SendKeyMessage()
+ // (or SendKeyError()) responses to the |reference_id|. Doing the best
+ // we can by keeping track of this in a queue, and assuming the responses
+ // come back in order.
+ wrapper->pending_key_request_reference_ids_.push(reference_id);
+ wrapper->current_key_request_reference_id_ =
+ CdmWrapper::kInvalidReferenceId;
+ }
+}
+
+template <class CdmInterface>
+CdmWrapper::Result PrefixedAddKey(CdmWrapper* wrapper,
+ CdmInterface* cdm,
+ uint32_t reference_id,
+ const uint8_t* response,
+ uint32_t response_size) {
+ const std::string session_id = wrapper->LookupSessionId(reference_id);
+ if (session_id.empty()) {
+ // Possible if UpdateSession() called before CreateSession().
+ return CdmWrapper::CALL_KEY_ERROR;
+ }
+
+ // CDM_1 and CDM_2 accept initdata, which is no longer needed.
+ // In it's place pass in NULL.
+ cdm::Status status = cdm->AddKey(
+ session_id.data(), session_id.size(), response, response_size, NULL, 0);
+ PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
+ if (status != cdm::kSuccess) {
+ // Some CDMs using Host_1/2 don't call keyerror, so send one.
+ return CdmWrapper::CALL_KEY_ERROR;
+ }
+
+ return CdmWrapper::CALL_KEY_ADDED;
+}
+
+template <class CdmInterface>
+CdmWrapper::Result PrefixedCancelKeyRequest(CdmWrapper* wrapper,
+ CdmInterface* cdm,
+ uint32_t reference_id) {
+ const std::string session_id = wrapper->LookupSessionId(reference_id);
+ if (session_id.empty()) {
+ // Possible if ReleaseSession() called before CreateSession().
+ return CdmWrapper::CALL_KEY_ERROR;
+ }
+
+ wrapper->session_map_.erase(reference_id);
+ cdm::Status status =
+ cdm->CancelKeyRequest(session_id.data(), session_id.size());
+
+ PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
+ if (status != cdm::kSuccess) {
+ // Some CDMs using Host_1/2 don't call keyerror, so send one.
+ return CdmWrapper::CALL_KEY_ERROR;
+ }
+
+ return CdmWrapper::NO_ACTION;
+}
+
// Specializations for ContentDecryptionModule_1.
+template <>
+void CdmWrapperImpl<cdm::ContentDecryptionModule_1>::CreateSession(
+ uint32_t reference_id,
+ const char* type,
+ uint32_t type_size,
+ const uint8_t* init_data,
+ uint32_t init_data_size) {
+ PrefixedGenerateKeyRequest(
+ this, cdm_, reference_id, type, type_size, init_data, init_data_size);
+}
+
+template <>
+CdmWrapper::Result CdmWrapperImpl<
+ cdm::ContentDecryptionModule_1>::UpdateSession(uint32_t reference_id,
+ const uint8_t* response,
+ uint32_t response_size) {
+ return PrefixedAddKey(this, cdm_, reference_id, response, response_size);
+}
+
+template <>
+CdmWrapper::Result CdmWrapperImpl<
+ cdm::ContentDecryptionModule_1>::ReleaseSession(uint32_t reference_id) {
+ return PrefixedCancelKeyRequest(this, cdm_, reference_id);
+}
+
template <> void CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
OnPlatformChallengeResponse(
const cdm::PlatformChallengeResponse& response) {
@@ -361,12 +412,39 @@ template <> cdm::Status CdmWrapperImpl<cdm::ContentDecryptionModule_1>::
return cdm::kSuccess;
}
+// Specializations for ContentDecryptionModule_2.
+
+template <>
+void CdmWrapperImpl<cdm::ContentDecryptionModule_2>::CreateSession(
+ uint32_t reference_id,
+ const char* type,
+ uint32_t type_size,
+ const uint8_t* init_data,
+ uint32_t init_data_size) {
+ PrefixedGenerateKeyRequest(
+ this, cdm_, reference_id, type, type_size, init_data, init_data_size);
+}
+
+template <>
+CdmWrapper::Result CdmWrapperImpl<
+ cdm::ContentDecryptionModule_2>::UpdateSession(uint32_t reference_id,
+ const uint8_t* response,
+ uint32_t response_size) {
+ return PrefixedAddKey(this, cdm_, reference_id, response, response_size);
+}
+
+template <>
+CdmWrapper::Result CdmWrapperImpl<
+ cdm::ContentDecryptionModule_2>::ReleaseSession(uint32_t reference_id) {
+ return PrefixedCancelKeyRequest(this, cdm_, reference_id);
+}
+
CdmWrapper* CdmWrapper::Create(const char* key_system,
uint32_t key_system_size,
GetCdmHostFunc get_cdm_host_func,
void* user_data) {
COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
- cdm::ContentDecryptionModule_2::kVersion,
+ cdm::ContentDecryptionModule_3::kVersion,
update_code_below);
// Ensure IsSupportedCdmInterfaceVersion matches this implementation.
@@ -378,6 +456,8 @@ CdmWrapper* CdmWrapper::Create(const char* key_system,
cdm::ContentDecryptionModule::kVersion + 1) &&
IsSupportedCdmInterfaceVersion(cdm::ContentDecryptionModule::kVersion) &&
IsSupportedCdmInterfaceVersion(
+ cdm::ContentDecryptionModule_2::kVersion) &&
+ IsSupportedCdmInterfaceVersion(
cdm::ContentDecryptionModule_1::kVersion) &&
!IsSupportedCdmInterfaceVersion(
cdm::ContentDecryptionModule_1::kVersion - 1));
@@ -390,6 +470,11 @@ CdmWrapper* CdmWrapper::Create(const char* key_system,
return cdm_wrapper;
// Try to see if the CDM supports older version(s) of the CDM interface.
+ cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_2>::Create(
+ key_system, key_system_size, get_cdm_host_func, user_data);
+ if (cdm_wrapper)
+ return cdm_wrapper;
+
cdm_wrapper = CdmWrapperImpl<cdm::ContentDecryptionModule_1>::Create(
key_system, key_system_size, get_cdm_host_func, user_data);
return cdm_wrapper;
@@ -400,7 +485,7 @@ CdmWrapper* CdmWrapper::Create(const char* key_system,
// does not have.
// Also update supported_cdm_versions.h.
COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
- cdm::ContentDecryptionModule_2::kVersion,
+ cdm::ContentDecryptionModule_3::kVersion,
ensure_cdm_wrapper_templates_have_old_version_support);
} // namespace media
diff --git a/media/cdm/ppapi/clear_key_cdm.cc b/media/cdm/ppapi/clear_key_cdm.cc
index 044cbb2..3fc10e1 100644
--- a/media/cdm/ppapi/clear_key_cdm.cc
+++ b/media/cdm/ppapi/clear_key_cdm.cc
@@ -171,43 +171,49 @@ ClearKeyCdm::Client::~Client() {}
void ClearKeyCdm::Client::Reset() {
status_ = kNone;
session_id_.clear();
- key_message_.clear();
- default_url_.clear();
+ message_.clear();
+ destination_url_.clear();
error_code_ = MediaKeys::kUnknownError;
system_code_ = 0;
}
-void ClearKeyCdm::Client::KeyAdded(uint32 reference_id) {
- status_ = static_cast<Status>(status_ | kKeyAdded);
+void ClearKeyCdm::Client::OnSessionCreated(uint32 reference_id,
+ const std::string& session_id) {
+ status_ = static_cast<Status>(status_ | kCreated);
+ session_id_ = session_id;
}
-void ClearKeyCdm::Client::KeyError(uint32 reference_id,
- media::MediaKeys::KeyError error_code,
- int system_code) {
- status_ = static_cast<Status>(status_ | kKeyError);
- error_code_ = error_code;
- system_code_ = system_code;
+void ClearKeyCdm::Client::OnSessionMessage(uint32 reference_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url) {
+ status_ = static_cast<Status>(status_ | kMessage);
+ message_ = message;
+ destination_url_ = destination_url;
}
-void ClearKeyCdm::Client::KeyMessage(uint32 reference_id,
- const std::vector<uint8>& message,
- const std::string& default_url) {
- status_ = static_cast<Status>(status_ | kKeyMessage);
- key_message_ = message;
- default_url_ = default_url;
+void ClearKeyCdm::Client::OnSessionReady(uint32 reference_id) {
+ status_ = static_cast<Status>(status_ | kReady);
}
-void ClearKeyCdm::Client::SetSessionId(uint32 reference_id,
- const std::string& session_id) {
- status_ = static_cast<Status>(status_ | kSetSessionId);
- session_id_ = session_id;
+void ClearKeyCdm::Client::OnSessionClosed(uint32 reference_id) {
+ status_ = static_cast<Status>(status_ | kClosed);
+}
+
+void ClearKeyCdm::Client::OnSessionError(uint32 reference_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) {
+ status_ = static_cast<Status>(status_ | kError);
+ error_code_ = error_code;
+ system_code_ = system_code;
}
ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, bool is_decrypt_only)
- : decryptor_(base::Bind(&Client::KeyAdded, base::Unretained(&client_)),
- base::Bind(&Client::KeyError, base::Unretained(&client_)),
- base::Bind(&Client::KeyMessage, base::Unretained(&client_)),
- base::Bind(&Client::SetSessionId, base::Unretained(&client_))),
+ : decryptor_(
+ base::Bind(&Client::OnSessionCreated, base::Unretained(&client_)),
+ base::Bind(&Client::OnSessionMessage, base::Unretained(&client_)),
+ base::Bind(&Client::OnSessionReady, base::Unretained(&client_)),
+ base::Bind(&Client::OnSessionClosed, base::Unretained(&client_)),
+ base::Bind(&Client::OnSessionError, base::Unretained(&client_))),
host_(host),
is_decrypt_only_(is_decrypt_only),
timer_delay_ms_(kInitialTimerDelayMs),
@@ -230,11 +236,11 @@ cdm::Status ClearKeyCdm::GenerateKeyRequest(const char* type,
DVLOG(1) << "GenerateKeyRequest()";
base::AutoLock auto_lock(client_lock_);
ScopedResetter<Client> auto_resetter(&client_);
- decryptor_.GenerateKeyRequest(MediaKeys::kInvalidReferenceId,
- std::string(type, type_size),
- init_data, init_data_size);
+ decryptor_.CreateSession(MediaKeys::kInvalidReferenceId,
+ std::string(type, type_size),
+ init_data, init_data_size);
- if (client_.status() != (Client::kKeyMessage | Client::kSetSessionId)) {
+ if (client_.status() != (Client::kMessage | Client::kCreated)) {
// Use values returned to client if possible.
host_->SendKeyError(client_.session_id().data(),
client_.session_id().size(),
@@ -245,9 +251,9 @@ cdm::Status ClearKeyCdm::GenerateKeyRequest(const char* type,
host_->SendKeyMessage(
client_.session_id().data(), client_.session_id().size(),
- reinterpret_cast<const char*>(&client_.key_message()[0]),
- client_.key_message().size(),
- client_.default_url().data(), client_.default_url().size());
+ reinterpret_cast<const char*>(&client_.message()[0]),
+ client_.message().size(),
+ client_.destination_url().data(), client_.destination_url().size());
// Only save the latest session ID for heartbeat messages.
heartbeat_session_id_ = client_.session_id();
@@ -262,13 +268,12 @@ cdm::Status ClearKeyCdm::AddKey(const char* session_id,
const uint8_t* key_id,
uint32_t key_id_size) {
DVLOG(1) << "AddKey()";
+ DCHECK(!key_id && !key_id_size);
base::AutoLock auto_lock(client_lock_);
ScopedResetter<Client> auto_resetter(&client_);
- decryptor_.AddKey(MediaKeys::kInvalidReferenceId,
- key, key_size,
- key_id, key_id_size);
+ decryptor_.UpdateSession(MediaKeys::kInvalidReferenceId, key, key_size);
- if (client_.status() != Client::kKeyAdded) {
+ if (client_.status() != Client::kReady) {
host_->SendKeyError(session_id, session_id_size,
static_cast<cdm::MediaKeyError>(client_.error_code()),
client_.system_code());
@@ -288,11 +293,11 @@ cdm::Status ClearKeyCdm::CancelKeyRequest(const char* session_id,
DVLOG(1) << "CancelKeyRequest()";
base::AutoLock auto_lock(client_lock_);
ScopedResetter<Client> auto_resetter(&client_);
- decryptor_.CancelKeyRequest(MediaKeys::kInvalidReferenceId);
+ decryptor_.ReleaseSession(MediaKeys::kInvalidReferenceId);
- // No message normally sent by CancelKeyRequest(), but if an error occurred,
+ // No message normally sent by Release(), but if an error occurred,
// report it as a failure.
- if (client_.status() == Client::kKeyError) {
+ if (client_.status() == Client::kError) {
host_->SendKeyError(session_id, session_id_size,
static_cast<cdm::MediaKeyError>(client_.error_code()),
client_.system_code());
diff --git a/media/cdm/ppapi/clear_key_cdm.h b/media/cdm/ppapi/clear_key_cdm.h
index 6ef4e04..4c5cb34 100644
--- a/media/cdm/ppapi/clear_key_cdm.h
+++ b/media/cdm/ppapi/clear_key_cdm.h
@@ -75,10 +75,11 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
// interface supports reference_id passing completely.
enum Status {
kNone = 0,
- kKeyAdded = 1 << 0,
- kKeyError = 1 << 1,
- kKeyMessage = 1 << 2,
- kSetSessionId = 1 << 3
+ kCreated = 1 << 0,
+ kMessage = 1 << 1,
+ kReady = 1 << 2,
+ kClosed = 1 << 3,
+ kError = 1 << 4
};
Client();
@@ -86,28 +87,29 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
Status status() { return status_; }
const std::string& session_id() { return session_id_; }
- const std::vector<uint8>& key_message() { return key_message_; }
- const std::string& default_url() { return default_url_; }
+ const std::vector<uint8>& message() { return message_; }
+ const std::string& destination_url() { return destination_url_; }
MediaKeys::KeyError error_code() { return error_code_; }
int system_code() { return system_code_; }
// Resets the Client to a clean state.
void Reset();
- void KeyAdded(uint32 reference_id);
- void KeyError(uint32 reference_id,
- MediaKeys::KeyError error_code,
- int system_code);
- void KeyMessage(uint32 reference_id,
- const std::vector<uint8>& message,
- const std::string& default_url);
- void SetSessionId(uint32 reference_id, const std::string& session_id);
+ void OnSessionCreated(uint32 reference_id, const std::string& session_id);
+ void OnSessionMessage(uint32 reference_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url);
+ void OnSessionReady(uint32 reference_id);
+ void OnSessionClosed(uint32 reference_id);
+ void OnSessionError(uint32 reference_id,
+ MediaKeys::KeyError error_code,
+ int system_code);
private:
Status status_;
std::string session_id_;
- std::vector<uint8> key_message_;
- std::string default_url_;
+ std::vector<uint8> message_;
+ std::string destination_url_;
MediaKeys::KeyError error_code_;
int system_code_;
};
diff --git a/media/cdm/ppapi/clear_key_cdm_common.h b/media/cdm/ppapi/clear_key_cdm_common.h
index d6ed59b..8f84397 100644
--- a/media/cdm/ppapi/clear_key_cdm_common.h
+++ b/media/cdm/ppapi/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 ClearKeyCdmInterface;
+typedef cdm::ContentDecryptionModule_2 ClearKeyCdmInterface;
typedef ClearKeyCdmInterface::Host ClearKeyCdmHost;
} // namespace media
diff --git a/media/cdm/ppapi/supported_cdm_versions.h b/media/cdm/ppapi/supported_cdm_versions.h
index 085eaf44..04723d8 100644
--- a/media/cdm/ppapi/supported_cdm_versions.h
+++ b/media/cdm/ppapi/supported_cdm_versions.h
@@ -21,12 +21,12 @@ bool IsSupportedCdmModuleVersion(int version) {
bool IsSupportedCdmInterfaceVersion(int version) {
COMPILE_ASSERT(cdm::ContentDecryptionModule::kVersion ==
- cdm::ContentDecryptionModule_2::kVersion,
+ cdm::ContentDecryptionModule_3::kVersion,
update_code_below);
switch(version) {
- // Latest.
- case cdm::ContentDecryptionModule::kVersion:
- // Older supported versions.
+ // Supported versions in decreasing order.
+ case cdm::ContentDecryptionModule_3::kVersion:
+ case cdm::ContentDecryptionModule_2::kVersion:
case cdm::ContentDecryptionModule_1::kVersion:
return true;
default:
@@ -36,12 +36,13 @@ bool IsSupportedCdmInterfaceVersion(int version) {
bool IsSupportedCdmHostVersion(int version) {
COMPILE_ASSERT(cdm::ContentDecryptionModule::Host::kVersion ==
- cdm::ContentDecryptionModule_2::Host::kVersion,
+ cdm::ContentDecryptionModule_3::Host::kVersion,
update_code_below);
switch(version) {
- // Supported versions in increasing order (there is no default).
- case cdm::Host_1::kVersion:
+ // Supported versions in decreasing order.
+ case cdm::Host_3::kVersion:
case cdm::Host_2::kVersion:
+ case cdm::Host_1::kVersion:
return true;
default:
return false;