From c8d4028a56c2baf53a33f94656c72d68c83bf46a Mon Sep 17 00:00:00 2001 From: "xhwang@chromium.org" Date: Sat, 27 Oct 2012 07:23:13 +0000 Subject: Add "type" in GenerateKeyRequest() and OnNeedKey(). The "type" information could help the CDM to parse the initialization data correctly. See for details: https://www.w3.org/Bugs/Public/show_bug.cgi?id=19096 TBR=viettrungluu@chromium.org BUG=none TEST=none Review URL: https://chromiumcodereview.appspot.com/11313016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164522 0039d316-1c4b-4281-b951-d872f2087c98 --- media/base/decryptor.h | 4 +++- media/base/decryptor_client.h | 3 +++ media/base/mock_filters.cc | 3 ++- media/base/mock_filters.h | 7 +++++-- media/base/stream_parser.h | 10 +++++++--- media/crypto/aes_decryptor.cc | 4 +++- media/crypto/aes_decryptor.h | 1 + media/crypto/aes_decryptor_unittest.cc | 4 ++-- media/filters/chunk_demuxer.cc | 5 +++-- media/filters/chunk_demuxer.h | 7 +++++-- media/filters/chunk_demuxer_unittest.cc | 12 ++++++++---- media/filters/pipeline_integration_test.cc | 8 +++++--- media/mp4/mp4_stream_parser.cc | 5 ++++- media/mp4/mp4_stream_parser_unittest.cc | 11 +++++++++-- media/webm/webm_stream_parser.cc | 5 ++++- webkit/media/crypto/ppapi/clear_key_cdm.cc | 4 +++- webkit/media/crypto/ppapi/clear_key_cdm.h | 2 ++ webkit/media/crypto/ppapi_decryptor.cc | 2 ++ webkit/media/crypto/ppapi_decryptor.h | 1 + webkit/media/crypto/proxy_decryptor.cc | 5 +++-- webkit/media/crypto/proxy_decryptor.h | 1 + webkit/media/crypto/proxy_decryptor_unittest.cc | 21 +++++++++++---------- webkit/media/webmediaplayer_impl.cc | 9 +++++++++ webkit/media/webmediaplayer_impl.h | 5 +++++ webkit/media/webmediaplayer_proxy.cc | 6 ++++-- webkit/media/webmediaplayer_proxy.h | 2 ++ webkit/plugins/ppapi/ppapi_plugin_instance.cc | 2 ++ webkit/plugins/ppapi/ppapi_plugin_instance.h | 1 + 28 files changed, 110 insertions(+), 40 deletions(-) diff --git a/media/base/decryptor.h b/media/base/decryptor.h index 37f5e7a..de293e9 100644 --- a/media/base/decryptor.h +++ b/media/base/decryptor.h @@ -64,11 +64,13 @@ class MEDIA_EXPORT Decryptor { Decryptor(); virtual ~Decryptor(); - // Generates a key request for the |key_system| with |init_data| provided. + // Generates a key request for the |key_system| with |type| and + // |init_data| provided. // Returns true if generating key request succeeded, false otherwise. // Note: AddKey() and CancelKeyRequest() should only be called after // GenerateKeyRequest() returns true. virtual bool GenerateKeyRequest(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length) = 0; diff --git a/media/base/decryptor_client.h b/media/base/decryptor_client.h index 9db50ce..dc64419 100644 --- a/media/base/decryptor_client.h +++ b/media/base/decryptor_client.h @@ -36,8 +36,11 @@ class DecryptorClient { // Signals that a key is needed for decryption. |key_system| and |session_id| // can be empty if the key system has not been selected. + // TODO(xhwang): Figure out if "type" is optional for NeedKey fired from the + // decoder. virtual void NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_length) = 0; diff --git a/media/base/mock_filters.cc b/media/base/mock_filters.cc index 249e531..d32501e 100644 --- a/media/base/mock_filters.cc +++ b/media/base/mock_filters.cc @@ -73,9 +73,10 @@ void MockDecryptorClient::KeyMessage(const std::string& key_system, void MockDecryptorClient::NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_length) { - NeedKeyMock(key_system, session_id, init_data.get(), init_data_length); + NeedKeyMock(key_system, session_id, type, init_data.get(), init_data_length); } MockFilterCollection::MockFilterCollection() diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 518a180..3c98ae8 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -196,7 +196,8 @@ class MockDecryptor : public Decryptor { MockDecryptor(); virtual ~MockDecryptor(); - MOCK_METHOD3(GenerateKeyRequest, bool(const std::string& key_system, + MOCK_METHOD4(GenerateKeyRequest, bool(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length)); MOCK_METHOD6(AddKey, void(const std::string& key_system, @@ -259,8 +260,9 @@ class MockDecryptorClient : public DecryptorClient { const uint8* message, int message_length, const std::string& default_url)); - MOCK_METHOD4(NeedKeyMock, void(const std::string& key_system, + MOCK_METHOD5(NeedKeyMock, void(const std::string& key_system, const std::string& session_id, + const std::string& type, const uint8* init_data, int init_data_length)); virtual void KeyMessage(const std::string& key_system, @@ -270,6 +272,7 @@ class MockDecryptorClient : public DecryptorClient { const std::string& default_url) OVERRIDE; virtual void NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_length) OVERRIDE; diff --git a/media/base/stream_parser.h b/media/base/stream_parser.h index 64a8c49..d4eb335 100644 --- a/media/base/stream_parser.h +++ b/media/base/stream_parser.h @@ -6,6 +6,7 @@ #define MEDIA_BASE_STREAM_PARSER_H_ #include +#include #include "base/callback_forward.h" #include "base/memory/ref_counted.h" @@ -58,12 +59,15 @@ class MEDIA_EXPORT StreamParser { typedef base::Callback NewMediaSegmentCB; // A new potentially encrypted stream has been parsed. - // First parameter - The initialization data associated with the stream. - // Second parameter - Number of bytes of the initialization data. + // First parameter - The type of the initialization data associated with the + // stream. + // Second parameter - The initialization data associated with the stream. + // Third parameter - Number of bytes of the initialization data. // Return value - True indicates that the initialization data is accepted. // False if something was wrong with the initialization data // and a parsing error should be signalled. - typedef base::Callback, int)> NeedKeyCB; + typedef base::Callback, int)> NeedKeyCB; // Initialize the parser with necessary callbacks. Must be called before any // data is passed to Parse(). |init_cb| will be called once enough data has diff --git a/media/crypto/aes_decryptor.cc b/media/crypto/aes_decryptor.cc index b971d4c..fe964f6c 100644 --- a/media/crypto/aes_decryptor.cc +++ b/media/crypto/aes_decryptor.cc @@ -134,11 +134,13 @@ AesDecryptor::~AesDecryptor() { } bool AesDecryptor::GenerateKeyRequest(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length) { std::string session_id_string(base::UintToString(next_session_id_++)); - // For now, just fire the event with the |init_data| as the request. + // For now, the AesDecryptor does not care about |key_system| and |type|; + // just fire the event with the |init_data| as the request. int message_length = init_data_length; scoped_array message(new uint8[message_length]); memcpy(message.get(), init_data, message_length); diff --git a/media/crypto/aes_decryptor.h b/media/crypto/aes_decryptor.h index 53fb813..966738b 100644 --- a/media/crypto/aes_decryptor.h +++ b/media/crypto/aes_decryptor.h @@ -35,6 +35,7 @@ class MEDIA_EXPORT AesDecryptor : public Decryptor { // Decryptor implementation. virtual bool GenerateKeyRequest(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length) OVERRIDE; virtual void AddKey(const std::string& key_system, diff --git a/media/crypto/aes_decryptor_unittest.cc b/media/crypto/aes_decryptor_unittest.cc index fdeba83..dac0208 100644 --- a/media/crypto/aes_decryptor_unittest.cc +++ b/media/crypto/aes_decryptor_unittest.cc @@ -240,10 +240,10 @@ class AesDecryptorTest : public testing::Test { protected: void GenerateKeyRequest(const uint8* key_id, int key_id_size) { - EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), + EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(""), NotNull(), Gt(0), "")) .WillOnce(SaveArg<1>(&session_id_string_)); - EXPECT_TRUE(decryptor_.GenerateKeyRequest(kClearKeySystem, + EXPECT_TRUE(decryptor_.GenerateKeyRequest(kClearKeySystem, "", key_id, key_id_size)); } diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index 5aa7995..c3cbbb7 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -1116,10 +1116,11 @@ bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that // this method can be removed and need_key_cb_ can be passed directly // to the parser. -bool ChunkDemuxer::OnNeedKey(scoped_array init_data, +bool ChunkDemuxer::OnNeedKey(const std::string& type, + scoped_array init_data, int init_data_size) { lock_.AssertAcquired(); - need_key_cb_.Run(init_data.Pass(), init_data_size); + need_key_cb_.Run(type, init_data.Pass(), init_data_size); return true; } diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index 3ec8160..6855b61 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h @@ -32,7 +32,8 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { kReachedIdLimit, // Reached ID limit. We can't handle any more IDs. }; - typedef base::Callback init_data, + typedef base::Callback init_data, int init_data_size)> NeedKeyCB; // |open_cb| Run when Initialize() is called to signal that the demuxer @@ -129,7 +130,9 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { const VideoDecoderConfig& video_config); bool OnAudioBuffers(const StreamParser::BufferQueue& buffers); bool OnVideoBuffers(const StreamParser::BufferQueue& buffers); - bool OnNeedKey(scoped_array init_data, int init_data_size); + bool OnNeedKey(const std::string& type, + scoped_array init_data, + int init_data_size); void OnNewMediaSegment(const std::string& source_id, base::TimeDelta start_timestamp); void OnEndOfMediaSegment(const std::string& source_id); diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc index eae8f69..8f4fa4e 100644 --- a/media/filters/chunk_demuxer_unittest.cc +++ b/media/filters/chunk_demuxer_unittest.cc @@ -58,6 +58,8 @@ static const char* kDefaultFirstClusterRange = "{ [0,46) }"; static const int kDefaultFirstClusterEndTimestamp = 66; static const int kDefaultSecondClusterEndTimestamp = 132; +static const char kWebMInitDataType[] = "video/webm"; + base::TimeDelta kDefaultDuration() { return base::TimeDelta::FromMilliseconds(201224); } @@ -732,9 +734,11 @@ class ChunkDemuxerTest : public testing::Test { // are not supported in mocked methods. Remove this when the issue is fixed // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use // std::string instead of scoped_array (http://crbug.com/130689). - MOCK_METHOD2(NeedKeyMock, void(const uint8* init_data, int init_data_size)); - void DemuxerNeedKey(scoped_array init_data, int init_data_size) { - NeedKeyMock(init_data.get(), init_data_size); + MOCK_METHOD3(NeedKeyMock, void(const std::string& type, + const uint8* init_data, int init_data_size)); + void DemuxerNeedKey(const std::string& type, + scoped_array init_data, int init_data_size) { + NeedKeyMock(type, init_data.get(), init_data_size); } MessageLoop message_loop_; @@ -766,7 +770,7 @@ TEST_F(ChunkDemuxerTest, TestInit) { if (is_audio_encrypted || is_video_encrypted) { int need_key_count = (is_audio_encrypted ? 1 : 0) + (is_video_encrypted ? 1 : 0); - EXPECT_CALL(*this, NeedKeyMock(NotNull(), 16)) + EXPECT_CALL(*this, NeedKeyMock(kWebMInitDataType, NotNull(), 16)) .Times(Exactly(need_key_count)); } diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc index ffafb0e..13e95a5 100644 --- a/media/filters/pipeline_integration_test.cc +++ b/media/filters/pipeline_integration_test.cc @@ -120,11 +120,12 @@ class MockMediaSource { AppendData(initial_append_size_); } - void DemuxerNeedKey(scoped_array init_data, int init_data_size) { + void DemuxerNeedKey(const std::string& type, + scoped_array init_data, int init_data_size) { DCHECK(init_data.get()); DCHECK_GT(init_data_size, 0); DCHECK(decryptor_client_); - decryptor_client_->NeedKey("", "", init_data.Pass(), init_data_size); + decryptor_client_->NeedKey("", "", type, init_data.Pass(), init_data_size); } private: @@ -175,6 +176,7 @@ class FakeDecryptorClient : public DecryptorClient { virtual void NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_length) { current_key_system_ = key_system; @@ -186,7 +188,7 @@ class FakeDecryptorClient : public DecryptorClient { if (current_key_system_.empty()) { DCHECK(current_session_id_.empty()); EXPECT_TRUE(decryptor_.GenerateKeyRequest( - kClearKeySystem, kInitData, arraysize(kInitData))); + kClearKeySystem, type, kInitData, arraysize(kInitData))); } EXPECT_FALSE(current_key_system_.empty()); diff --git a/media/mp4/mp4_stream_parser.cc b/media/mp4/mp4_stream_parser.cc index c600537..07135d8 100644 --- a/media/mp4/mp4_stream_parser.cc +++ b/media/mp4/mp4_stream_parser.cc @@ -20,6 +20,9 @@ namespace media { namespace mp4 { +// TODO(xhwang): Figure out the init data type appropriately once it's spec'ed. +static const char kMp4InitDataType[] = "video/mp4"; + MP4StreamParser::MP4StreamParser(bool has_sbr) : state_(kWaitingForInit), moof_head_(0), @@ -287,7 +290,7 @@ bool MP4StreamParser::EmitNeedKeyIfNecessary( headers[i].raw_box.size()); pos += headers[i].raw_box.size(); } - return need_key_cb_.Run(init_data.Pass(), total_size); + return need_key_cb_.Run(kMp4InitDataType, init_data.Pass(), total_size); } bool MP4StreamParser::PrepareAVCBuffer( diff --git a/media/mp4/mp4_stream_parser_unittest.cc b/media/mp4/mp4_stream_parser_unittest.cc index 6d7221a..81dbdd8 100644 --- a/media/mp4/mp4_stream_parser_unittest.cc +++ b/media/mp4/mp4_stream_parser_unittest.cc @@ -23,6 +23,9 @@ using base::TimeDelta; namespace media { namespace mp4 { +// TODO(xhwang): Figure out the init data type appropriately once it's spec'ed. +static const char kMp4InitDataType[] = "video/mp4"; + class MP4StreamParserTest : public testing::Test { public: MP4StreamParserTest() @@ -54,7 +57,7 @@ class MP4StreamParserTest : public testing::Test { void InitF(bool init_ok, base::TimeDelta duration) { DVLOG(1) << "InitF: ok=" << init_ok - << ", dur=" << duration.InMilliseconds(); + << ", dur=" << duration.InMilliseconds(); } bool NewConfigF(const AudioDecoderConfig& ac, const VideoDecoderConfig& vc) { @@ -76,8 +79,12 @@ class MP4StreamParserTest : public testing::Test { return true; } - bool KeyNeededF(scoped_array init_data, int init_data_size) { + bool KeyNeededF(const std::string& type, + scoped_array init_data, int init_data_size) { DVLOG(1) << "KeyNeededF: " << init_data_size; + EXPECT_EQ(kMp4InitDataType, type); + EXPECT_TRUE(init_data.get()); + EXPECT_GT(init_data_size, 0); return true; } diff --git a/media/webm/webm_stream_parser.cc b/media/webm/webm_stream_parser.cc index 2e34ed9..8cf0999 100644 --- a/media/webm/webm_stream_parser.cc +++ b/media/webm/webm_stream_parser.cc @@ -19,6 +19,9 @@ namespace media { +// TODO(xhwang): Figure out the init data type appropriately once it's spec'ed. +static const char kWebMInitDataType[] = "video/webm"; + // Helper class that uses FFmpeg to create AudioDecoderConfig & // VideoDecoderConfig objects. // @@ -474,7 +477,7 @@ void WebMStreamParser::FireNeedKey(const std::string& key_id) { DCHECK_GT(key_id_size, 0); scoped_array key_id_array(new uint8[key_id_size]); memcpy(key_id_array.get(), key_id.data(), key_id_size); - need_key_cb_.Run(key_id_array.Pass(), key_id_size); + need_key_cb_.Run(kWebMInitDataType, key_id_array.Pass(), key_id_size); } } // namespace media diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.cc b/webkit/media/crypto/ppapi/clear_key_cdm.cc index 83cf00c..7d11eb3 100644 --- a/webkit/media/crypto/ppapi/clear_key_cdm.cc +++ b/webkit/media/crypto/ppapi/clear_key_cdm.cc @@ -168,6 +168,7 @@ void ClearKeyCdm::Client::KeyMessage(const std::string& key_system, void ClearKeyCdm::Client::NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_length) { // In the current implementation of AesDecryptor, NeedKey is not used. @@ -197,7 +198,8 @@ cdm::Status ClearKeyCdm::GenerateKeyRequest(const uint8_t* init_data, DVLOG(1) << "GenerateKeyRequest()"; base::AutoLock auto_lock(client_lock_); ScopedResetter auto_resetter(&client_); - decryptor_.GenerateKeyRequest("", init_data, init_data_size); + // TODO(tomfinegan): Pass "type" here once ContentDecryptionModule is updated. + decryptor_.GenerateKeyRequest("", "", init_data, init_data_size); if (client_.status() != Client::kKeyMessage) return cdm::kSessionError; diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.h b/webkit/media/crypto/ppapi/clear_key_cdm.h index 95c188f..9f08678 100644 --- a/webkit/media/crypto/ppapi/clear_key_cdm.h +++ b/webkit/media/crypto/ppapi/clear_key_cdm.h @@ -45,6 +45,7 @@ class ClearKeyCdm : public cdm::ContentDecryptionModule { virtual ~ClearKeyCdm(); // ContentDecryptionModule implementation. + // TODO(tomfinegan): Update ContentDecryptionModule to pass "type" through. virtual cdm::Status GenerateKeyRequest( const uint8_t* init_data, int init_data_size, @@ -109,6 +110,7 @@ class ClearKeyCdm : public cdm::ContentDecryptionModule { const std::string& default_url) OVERRIDE; virtual void NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_length) OVERRIDE; diff --git a/webkit/media/crypto/ppapi_decryptor.cc b/webkit/media/crypto/ppapi_decryptor.cc index 8a2d7a1..5ae10c3 100644 --- a/webkit/media/crypto/ppapi_decryptor.cc +++ b/webkit/media/crypto/ppapi_decryptor.cc @@ -40,6 +40,7 @@ PpapiDecryptor::~PpapiDecryptor() { } bool PpapiDecryptor::GenerateKeyRequest(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length) { DVLOG(2) << "GenerateKeyRequest()"; @@ -50,6 +51,7 @@ bool PpapiDecryptor::GenerateKeyRequest(const std::string& key_system, // data type conversions. if (!cdm_plugin_->GenerateKeyRequest( key_system, + type, std::string(reinterpret_cast(init_data), init_data_length))) { ReportFailureToCallPlugin(key_system, ""); diff --git a/webkit/media/crypto/ppapi_decryptor.h b/webkit/media/crypto/ppapi_decryptor.h index b65eb19..c27e046 100644 --- a/webkit/media/crypto/ppapi_decryptor.h +++ b/webkit/media/crypto/ppapi_decryptor.h @@ -40,6 +40,7 @@ class PpapiDecryptor : public media::Decryptor { // media::Decryptor implementation. virtual bool GenerateKeyRequest(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length) OVERRIDE; virtual void AddKey(const std::string& key_system, diff --git a/webkit/media/crypto/proxy_decryptor.cc b/webkit/media/crypto/proxy_decryptor.cc index 6ef4a5e..ea1ffba 100644 --- a/webkit/media/crypto/proxy_decryptor.cc +++ b/webkit/media/crypto/proxy_decryptor.cc @@ -58,7 +58,7 @@ static void FireNeedKey(media::DecryptorClient* client, std::string key_id = encrypted->GetDecryptConfig()->key_id(); scoped_array 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()); + client->NeedKey("", "", "", key_id_array.Pass(), key_id.size()); } ProxyDecryptor::ProxyDecryptor( @@ -101,6 +101,7 @@ void ProxyDecryptor::RequestDecryptorNotification( } bool ProxyDecryptor::GenerateKeyRequest(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length) { // We do not support run-time switching of decryptors. GenerateKeyRequest() @@ -117,7 +118,7 @@ bool ProxyDecryptor::GenerateKeyRequest(const std::string& key_system, } } - if (!decryptor_->GenerateKeyRequest(key_system, + if (!decryptor_->GenerateKeyRequest(key_system, type, init_data, init_data_length)) { decryptor_.reset(); return false; diff --git a/webkit/media/crypto/proxy_decryptor.h b/webkit/media/crypto/proxy_decryptor.h index 9f65a6d..6ca0027 100644 --- a/webkit/media/crypto/proxy_decryptor.h +++ b/webkit/media/crypto/proxy_decryptor.h @@ -54,6 +54,7 @@ class ProxyDecryptor : public media::Decryptor { // media::Decryptor implementation. virtual bool GenerateKeyRequest(const std::string& key_system, + const std::string& type, const uint8* init_data, int init_data_length) OVERRIDE; virtual void AddKey(const std::string& key_system, diff --git a/webkit/media/crypto/proxy_decryptor_unittest.cc b/webkit/media/crypto/proxy_decryptor_unittest.cc index 759e68c..1f85a3d 100644 --- a/webkit/media/crypto/proxy_decryptor_unittest.cc +++ b/webkit/media/crypto/proxy_decryptor_unittest.cc @@ -29,6 +29,7 @@ using media::Decryptor; namespace webkit_media { static const uint8 kFakeKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 }; +static const int kFakeKeyIdSize = arraysize(kFakeKeyId); static const uint8 kFakeIv[DecryptConfig::kDecryptionKeySize] = { 0 }; static const char kFakeKeySystem[] = "system.key.fake"; static const char kFakeSessionId[] = "FakeSessionId"; @@ -44,7 +45,7 @@ static scoped_refptr CreateFakeEncryptedBuffer() { encrypted_buffer->SetDecryptConfig(scoped_ptr( new DecryptConfig( std::string(reinterpret_cast(kFakeKeyId), - arraysize(kFakeKeyId)), + kFakeKeyIdSize), std::string(reinterpret_cast(kFakeIv), DecryptConfig::kDecryptionKeySize), encrypted_frame_offset, @@ -94,11 +95,11 @@ class ProxyDecryptorTest : public testing::Test { // hence always use fake key IDs and keys. void AddKey() { EXPECT_CALL(*real_decryptor_, AddKey(kFakeKeySystem, - kFakeKeyId, arraysize(kFakeKeyId), + kFakeKeyId, kFakeKeyIdSize, kFakeKey, arraysize(kFakeKey), kFakeSessionId)); proxy_decryptor_.AddKey(kFakeKeySystem, - kFakeKeyId, arraysize(kFakeKeyId), + kFakeKeyId, kFakeKeyIdSize, kFakeKey, arraysize(kFakeKey), kFakeSessionId); } @@ -163,7 +164,7 @@ TEST_F(ProxyDecryptorTest, NormalDecryption_NoKey) { EXPECT_CALL(*real_decryptor_, Decrypt(stream_type_, encrypted_buffer_, _)) .WillOnce(RunDecryptCB(Decryptor::kNoKey, null_buffer_)); - EXPECT_CALL(client_, NeedKeyMock("", "", NotNull(), arraysize(kFakeKeyId))); + EXPECT_CALL(client_, NeedKeyMock("", "", "", NotNull(), kFakeKeyIdSize)); proxy_decryptor_.Decrypt(stream_type_, encrypted_buffer_, decrypt_cb_); EXPECT_CALL(*this, DeliverBuffer(Decryptor::kSuccess, null_buffer_)); @@ -172,7 +173,7 @@ TEST_F(ProxyDecryptorTest, NormalDecryption_NoKey) { // Tests the case where Decrypt() is called after the right key is added. TEST_F(ProxyDecryptorTest, DecryptBeforeAddKey) { - EXPECT_CALL(client_, NeedKeyMock("", "", NotNull(), arraysize(kFakeKeyId))); + EXPECT_CALL(client_, NeedKeyMock("", "", "", NotNull(), kFakeKeyIdSize)); GenerateKeyRequest(); EXPECT_CALL(*real_decryptor_, Decrypt(stream_type_, encrypted_buffer_, _)) .WillOnce(RunDecryptCB(Decryptor::kNoKey, null_buffer_)); @@ -190,7 +191,7 @@ TEST_F(ProxyDecryptorTest, DecryptBeforeAddKey) { // Tests the case where Decrypt() is called before GKR() and the right key is // added. TEST_F(ProxyDecryptorTest, DecryptBeforeGenerateKeyRequest) { - EXPECT_CALL(client_, NeedKeyMock("", "", NotNull(), arraysize(kFakeKeyId))); + EXPECT_CALL(client_, NeedKeyMock("", "", "", NotNull(), kFakeKeyIdSize)); proxy_decryptor_.Decrypt(stream_type_, encrypted_buffer_, decrypt_cb_); EXPECT_CALL(*real_decryptor_, Decrypt(stream_type_, encrypted_buffer_, _)) @@ -206,7 +207,7 @@ TEST_F(ProxyDecryptorTest, DecryptBeforeGenerateKeyRequest) { // Tests the case where multiple AddKey() is called to add some irrelevant keys // before the real key that can decrypt |encrypted_buffer_| is added. TEST_F(ProxyDecryptorTest, MultipleAddKeys) { - EXPECT_CALL(client_, NeedKeyMock("", "", NotNull(), arraysize(kFakeKeyId))) + EXPECT_CALL(client_, NeedKeyMock("", "", "", NotNull(), kFakeKeyIdSize)) .Times(AtLeast(1)); proxy_decryptor_.Decrypt(stream_type_, encrypted_buffer_, decrypt_cb_); @@ -257,7 +258,7 @@ TEST_F(ProxyDecryptorTest, AddKeyAfterDecryptButBeforeNoKeyReturned) { // GenerateKeyRequest is called. In this case, the decryptor was not even // created! TEST_F(ProxyDecryptorTest, CancelDecryptWithoutGenerateKeyRequestCalled) { - EXPECT_CALL(client_, NeedKeyMock("", "", NotNull(), arraysize(kFakeKeyId))) + EXPECT_CALL(client_, NeedKeyMock("", "", "", NotNull(), kFakeKeyIdSize)) .Times(AtLeast(1)); proxy_decryptor_.Decrypt(stream_type_, encrypted_buffer_, decrypt_cb_); @@ -271,7 +272,7 @@ TEST_F(ProxyDecryptorTest, CancelDecryptWithoutGenerateKeyRequestCalled) { // Test the case where we cancel the pending decryption callback when it's // stored in the ProxyDecryptor. TEST_F(ProxyDecryptorTest, CancelDecryptWhenDecryptPendingInProxyDecryptor) { - EXPECT_CALL(client_, NeedKeyMock("", "", NotNull(), arraysize(kFakeKeyId))) + EXPECT_CALL(client_, NeedKeyMock("", "", "", NotNull(), kFakeKeyIdSize)) .Times(AtLeast(1)); EXPECT_CALL(*real_decryptor_, Decrypt(stream_type_, encrypted_buffer_, _)) .WillRepeatedly(RunDecryptCB(Decryptor::kNoKey, null_buffer_)); @@ -311,7 +312,7 @@ TEST_F(ProxyDecryptorTest, CancelDecryptWhenDecryptPendingInRealDecryptor) { // Test the case where we try to decrypt again after the previous decrypt was // canceled. TEST_F(ProxyDecryptorTest, DecryptAfterCancelDecrypt) { - EXPECT_CALL(client_, NeedKeyMock("", "", NotNull(), arraysize(kFakeKeyId))) + EXPECT_CALL(client_, NeedKeyMock("", "", "", NotNull(), kFakeKeyIdSize)) .Times(AtLeast(1)); EXPECT_CALL(*real_decryptor_, Decrypt(stream_type_, encrypted_buffer_, _)) .WillRepeatedly(RunDecryptCB(Decryptor::kNoKey, null_buffer_)); diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc index 12d277b..87e1079 100644 --- a/webkit/media/webmediaplayer_impl.cc +++ b/webkit/media/webmediaplayer_impl.cc @@ -799,7 +799,11 @@ WebMediaPlayerImpl::GenerateKeyRequestInternal( << std::string(reinterpret_cast(init_data), static_cast(init_data_length)); + // TODO(xhwang): We assume all streams are from the same container (thus have + // the same "type") for now. In the future, the "type" should be passed down + // from the application. if (!decryptor_.GenerateKeyRequest(key_system.utf8(), + init_data_type_, init_data, init_data_length)) { current_key_system_.reset(); return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; @@ -1013,12 +1017,17 @@ void WebMediaPlayerImpl::OnKeyAdded(const std::string& key_system, void WebMediaPlayerImpl::OnNeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_size) { DCHECK_EQ(main_loop_, MessageLoop::current()); UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1); + DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); + if (init_data_type_.empty()) + init_data_type_ = type; + GetClient()->keyNeeded(WebString::fromUTF8(key_system), WebString::fromUTF8(session_id), init_data.get(), diff --git a/webkit/media/webmediaplayer_impl.h b/webkit/media/webmediaplayer_impl.h index 385e030..6d54110 100644 --- a/webkit/media/webmediaplayer_impl.h +++ b/webkit/media/webmediaplayer_impl.h @@ -245,6 +245,7 @@ class WebMediaPlayerImpl int message_length, const std::string& default_url); void OnNeedKey(const std::string& key_system, + const std::string& type, const std::string& session_id, scoped_array init_data, int init_data_size); @@ -364,6 +365,10 @@ class WebMediaPlayerImpl scoped_refptr chunk_demuxer_; + // Temporary for EME v0.1. In the future the init data type should be passed + // through GenerateKeyRequest() directly from WebKit. + std::string init_data_type_; + DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); }; diff --git a/webkit/media/webmediaplayer_proxy.cc b/webkit/media/webmediaplayer_proxy.cc index 05fe0d0..13941bf 100644 --- a/webkit/media/webmediaplayer_proxy.cc +++ b/webkit/media/webmediaplayer_proxy.cc @@ -135,10 +135,11 @@ void WebMediaPlayerProxy::KeyMessage(const std::string& key_system, void WebMediaPlayerProxy::NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_size) { render_loop_->PostTask(FROM_HERE, base::Bind( - &WebMediaPlayerProxy::NeedKeyTask, this, key_system, session_id, + &WebMediaPlayerProxy::NeedKeyTask, this, key_system, session_id, type, base::Passed(&init_data), init_data_size)); } @@ -172,11 +173,12 @@ void WebMediaPlayerProxy::KeyMessageTask(const std::string& key_system, void WebMediaPlayerProxy::NeedKeyTask(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_size) { DCHECK(render_loop_->BelongsToCurrentThread()); if (webmediaplayer_) - webmediaplayer_->OnNeedKey(key_system, session_id, + webmediaplayer_->OnNeedKey(key_system, session_id, type, init_data.Pass(), init_data_size); } diff --git a/webkit/media/webmediaplayer_proxy.h b/webkit/media/webmediaplayer_proxy.h index 35d5630..2c474ad 100644 --- a/webkit/media/webmediaplayer_proxy.h +++ b/webkit/media/webmediaplayer_proxy.h @@ -85,6 +85,7 @@ class WebMediaPlayerProxy const std::string& default_url) OVERRIDE; virtual void NeedKey(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_size) OVERRIDE; @@ -115,6 +116,7 @@ class WebMediaPlayerProxy // Notify |webmediaplayer_| that a key is needed for decryption. void NeedKeyTask(const std::string& key_system, const std::string& session_id, + const std::string& type, scoped_array init_data, int init_data_size); diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc index 1409d78..749f469 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc @@ -1624,6 +1624,7 @@ void PluginInstance::set_decrypt_client( } bool PluginInstance::GenerateKeyRequest(const std::string& key_system, + const std::string& type, const std::string& init_data) { if (!LoadContentDecryptorInterface()) return false; @@ -1634,6 +1635,7 @@ bool PluginInstance::GenerateKeyRequest(const std::string& key_system, PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( init_data.size(), init_data.data()); + // TODO(tomfinegan): Pass "type" once PPP_ContentDecryptor_Private is updated. plugin_decryption_interface_->GenerateKeyRequest( pp_instance(), StringVar::StringToPPVar(key_system), diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h index 3bd03f4..9d7d178 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.h +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h @@ -257,6 +257,7 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : // TODO(tomfinegan): Move decryptor methods to delegate class. void set_decrypt_client(media::DecryptorClient* client); bool GenerateKeyRequest(const std::string& key_system, + const std::string& type, const std::string& init_data); bool AddKey(const std::string& session_id, const std::string& key, -- cgit v1.1