Remove the webkit_media target.
[chromium-blink-merge.git] / content / renderer / media / crypto / ppapi_decryptor.cc
blob74188fb97ad390b3384286d49c55c8bd7f3e9841
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/media/crypto/ppapi_decryptor.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "media/base/audio_decoder_config.h"
16 #include "media/base/data_buffer.h"
17 #include "media/base/decoder_buffer.h"
18 #include "media/base/video_decoder_config.h"
19 #include "media/base/video_frame.h"
20 #include "webkit/plugins/ppapi/content_decryptor_delegate.h"
21 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
23 namespace content {
25 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
26 const std::string& key_system,
27 const scoped_refptr<webkit::ppapi::PluginInstance>& plugin_instance,
28 const media::KeyAddedCB& key_added_cb,
29 const media::KeyErrorCB& key_error_cb,
30 const media::KeyMessageCB& key_message_cb,
31 const base::Closure& destroy_plugin_cb) {
32 webkit::ppapi::ContentDecryptorDelegate* plugin_cdm_delegate =
33 plugin_instance->GetContentDecryptorDelegate();
34 if (!plugin_cdm_delegate) {
35 DVLOG(1) << "PpapiDecryptor: plugin cdm delegate creation failed.";
36 return scoped_ptr<PpapiDecryptor>();
39 plugin_cdm_delegate->Initialize(key_system);
41 return scoped_ptr<PpapiDecryptor>(new PpapiDecryptor(plugin_instance,
42 plugin_cdm_delegate,
43 key_added_cb,
44 key_error_cb,
45 key_message_cb,
46 destroy_plugin_cb));
49 PpapiDecryptor::PpapiDecryptor(
50 const scoped_refptr<webkit::ppapi::PluginInstance>& plugin_instance,
51 webkit::ppapi::ContentDecryptorDelegate* plugin_cdm_delegate,
52 const media::KeyAddedCB& key_added_cb,
53 const media::KeyErrorCB& key_error_cb,
54 const media::KeyMessageCB& key_message_cb,
55 const base::Closure& destroy_plugin_cb)
56 : plugin_instance_(plugin_instance),
57 plugin_cdm_delegate_(plugin_cdm_delegate),
58 key_added_cb_(key_added_cb),
59 key_error_cb_(key_error_cb),
60 key_message_cb_(key_message_cb),
61 destroy_plugin_cb_(destroy_plugin_cb),
62 render_loop_proxy_(base::MessageLoopProxy::current()),
63 weak_ptr_factory_(this),
64 weak_this_(weak_ptr_factory_.GetWeakPtr()) {
65 DCHECK(plugin_instance_.get());
67 plugin_cdm_delegate_->SetKeyEventCallbacks(
68 base::Bind(&PpapiDecryptor::KeyAdded, weak_this_),
69 base::Bind(&PpapiDecryptor::KeyError, weak_this_),
70 base::Bind(&PpapiDecryptor::KeyMessage, weak_this_));
73 PpapiDecryptor::~PpapiDecryptor() {
74 plugin_cdm_delegate_ = NULL;
75 plugin_instance_ = NULL;
76 destroy_plugin_cb_.Run();
79 bool PpapiDecryptor::GenerateKeyRequest(const std::string& type,
80 const uint8* init_data,
81 int init_data_length) {
82 DVLOG(2) << "GenerateKeyRequest()";
83 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
84 DCHECK(plugin_cdm_delegate_);
86 if (!plugin_cdm_delegate_->GenerateKeyRequest(
87 type, init_data, init_data_length)) {
88 ReportFailureToCallPlugin(std::string());
89 return false;
92 return true;
95 void PpapiDecryptor::AddKey(const uint8* key,
96 int key_length,
97 const uint8* init_data,
98 int init_data_length,
99 const std::string& session_id) {
100 DVLOG(2) << "AddKey()";
101 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
103 if (!plugin_cdm_delegate_->AddKey(
104 session_id, key, key_length, init_data, init_data_length)) {
105 ReportFailureToCallPlugin(session_id);
108 if (!new_audio_key_cb_.is_null())
109 new_audio_key_cb_.Run();
111 if (!new_video_key_cb_.is_null())
112 new_video_key_cb_.Run();
115 void PpapiDecryptor::CancelKeyRequest(const std::string& session_id) {
116 DVLOG(2) << "CancelKeyRequest()";
117 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
119 if (!plugin_cdm_delegate_->CancelKeyRequest(session_id))
120 ReportFailureToCallPlugin(session_id);
123 media::Decryptor* PpapiDecryptor::GetDecryptor() {
124 #if defined(GOOGLE_TV)
125 // Google TV only uses PpapiDecrytor as a MediaKeys and does not need the
126 // Decryptor interface of the PpapiDecryptor.
127 // Details: If we don't do this GTV will be broken. The reason is that during
128 // initialization, MediaSourceDelegate tries to use DecryptingDemuxerStream
129 // to decrypt the stream in the renderer process (for ClearKey support).
130 // However, for GTV, PpapiDecryptor cannot do decryption at all. By returning
131 // NULL, DDS init will fail and we fallback to what GTV used to do.
132 return NULL;
133 #else
134 return this;
135 #endif // defined(GOOGLE_TV)
138 void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type,
139 const NewKeyCB& new_key_cb) {
140 switch (stream_type) {
141 case kAudio:
142 new_audio_key_cb_ = new_key_cb;
143 break;
144 case kVideo:
145 new_video_key_cb_ = new_key_cb;
146 break;
147 default:
148 NOTREACHED();
152 void PpapiDecryptor::Decrypt(
153 StreamType stream_type,
154 const scoped_refptr<media::DecoderBuffer>& encrypted,
155 const DecryptCB& decrypt_cb) {
156 if (!render_loop_proxy_->BelongsToCurrentThread()) {
157 render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
158 &PpapiDecryptor::Decrypt, weak_this_,
159 stream_type, encrypted, decrypt_cb));
160 return;
163 DVLOG(3) << "Decrypt() - stream_type: " << stream_type;
164 if (!plugin_cdm_delegate_->Decrypt(stream_type, encrypted, decrypt_cb))
165 decrypt_cb.Run(kError, NULL);
168 void PpapiDecryptor::CancelDecrypt(StreamType stream_type) {
169 DVLOG(1) << "CancelDecrypt() - stream_type: " << stream_type;
170 plugin_cdm_delegate_->CancelDecrypt(stream_type);
173 void PpapiDecryptor::InitializeAudioDecoder(
174 const media::AudioDecoderConfig& config,
175 const DecoderInitCB& init_cb) {
176 if (!render_loop_proxy_->BelongsToCurrentThread()) {
177 render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
178 &PpapiDecryptor::InitializeAudioDecoder, weak_this_, config, init_cb));
179 return;
182 DVLOG(2) << "InitializeAudioDecoder()";
183 DCHECK(config.is_encrypted());
184 DCHECK(config.IsValidConfig());
186 audio_decoder_init_cb_ = init_cb;
187 if (!plugin_cdm_delegate_->InitializeAudioDecoder(config, base::Bind(
188 &PpapiDecryptor::OnDecoderInitialized, weak_this_, kAudio))) {
189 base::ResetAndReturn(&audio_decoder_init_cb_).Run(false);
190 return;
194 void PpapiDecryptor::InitializeVideoDecoder(
195 const media::VideoDecoderConfig& config,
196 const DecoderInitCB& init_cb) {
197 if (!render_loop_proxy_->BelongsToCurrentThread()) {
198 render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
199 &PpapiDecryptor::InitializeVideoDecoder, weak_this_, config, init_cb));
200 return;
203 DVLOG(2) << "InitializeVideoDecoder()";
204 DCHECK(config.is_encrypted());
205 DCHECK(config.IsValidConfig());
207 video_decoder_init_cb_ = init_cb;
208 if (!plugin_cdm_delegate_->InitializeVideoDecoder(config, base::Bind(
209 &PpapiDecryptor::OnDecoderInitialized, weak_this_, kVideo))) {
210 base::ResetAndReturn(&video_decoder_init_cb_).Run(false);
211 return;
215 void PpapiDecryptor::DecryptAndDecodeAudio(
216 const scoped_refptr<media::DecoderBuffer>& encrypted,
217 const AudioDecodeCB& audio_decode_cb) {
218 if (!render_loop_proxy_->BelongsToCurrentThread()) {
219 render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
220 &PpapiDecryptor::DecryptAndDecodeAudio, weak_this_,
221 encrypted, audio_decode_cb));
222 return;
225 DVLOG(3) << "DecryptAndDecodeAudio()";
226 if (!plugin_cdm_delegate_->DecryptAndDecodeAudio(encrypted, audio_decode_cb))
227 audio_decode_cb.Run(kError, AudioBuffers());
230 void PpapiDecryptor::DecryptAndDecodeVideo(
231 const scoped_refptr<media::DecoderBuffer>& encrypted,
232 const VideoDecodeCB& video_decode_cb) {
233 if (!render_loop_proxy_->BelongsToCurrentThread()) {
234 render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
235 &PpapiDecryptor::DecryptAndDecodeVideo, weak_this_,
236 encrypted, video_decode_cb));
237 return;
240 DVLOG(3) << "DecryptAndDecodeVideo()";
241 if (!plugin_cdm_delegate_->DecryptAndDecodeVideo(encrypted, video_decode_cb))
242 video_decode_cb.Run(kError, NULL);
245 void PpapiDecryptor::ResetDecoder(StreamType stream_type) {
246 if (!render_loop_proxy_->BelongsToCurrentThread()) {
247 render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
248 &PpapiDecryptor::ResetDecoder, weak_this_, stream_type));
249 return;
252 DVLOG(2) << "ResetDecoder() - stream_type: " << stream_type;
253 plugin_cdm_delegate_->ResetDecoder(stream_type);
256 void PpapiDecryptor::DeinitializeDecoder(StreamType stream_type) {
257 if (!render_loop_proxy_->BelongsToCurrentThread()) {
258 render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
259 &PpapiDecryptor::DeinitializeDecoder, weak_this_, stream_type));
260 return;
263 DVLOG(2) << "DeinitializeDecoder() - stream_type: " << stream_type;
264 plugin_cdm_delegate_->DeinitializeDecoder(stream_type);
267 void PpapiDecryptor::ReportFailureToCallPlugin(const std::string& session_id) {
268 DVLOG(1) << "Failed to call plugin.";
269 key_error_cb_.Run(session_id, kUnknownError, 0);
272 void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type,
273 bool success) {
274 switch (stream_type) {
275 case kAudio:
276 DCHECK(!audio_decoder_init_cb_.is_null());
277 base::ResetAndReturn(&audio_decoder_init_cb_).Run(success);
278 break;
279 case kVideo:
280 DCHECK(!video_decoder_init_cb_.is_null());
281 base::ResetAndReturn(&video_decoder_init_cb_).Run(success);
282 break;
283 default:
284 NOTREACHED();
288 void PpapiDecryptor::KeyAdded(const std::string& session_id) {
289 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
290 key_added_cb_.Run(session_id);
293 void PpapiDecryptor::KeyError(const std::string& session_id,
294 media::MediaKeys::KeyError error_code,
295 int system_code) {
296 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
297 key_error_cb_.Run(session_id, error_code, system_code);
300 void PpapiDecryptor::KeyMessage(const std::string& session_id,
301 const std::vector<uint8>& message,
302 const std::string& default_url) {
303 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
304 key_message_cb_.Run(session_id, message, default_url);
307 } // namespace content