1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/renderer/media/crypto/proxy_decryptor.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/renderer/media/crypto/content_decryption_module_factory.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace content {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS)
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::DestroyHelperPlugin() {
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ContentDecryptionModuleFactory::DestroyHelperPlugin(
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_media_player_client_);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif  // defined(ENABLE_PEPPER_CDMS)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyDecryptor::ProxyDecryptor(
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(ENABLE_PEPPER_CDMS)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebKit::WebMediaPlayerClient* web_media_player_client,
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebKit::WebFrame* web_frame,
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#elif defined(OS_ANDROID)
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    WebMediaPlayerProxyAndroid* proxy,
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int media_keys_id,
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif  // defined(ENABLE_PEPPER_CDMS)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const media::KeyAddedCB& key_added_cb,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const media::KeyErrorCB& key_error_cb,
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const media::KeyMessageCB& key_message_cb)
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : weak_ptr_factory_(this),
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(ENABLE_PEPPER_CDMS)
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_media_player_client_(web_media_player_client),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      web_frame_(web_frame),
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#elif defined(OS_ANDROID)
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      proxy_(proxy),
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      media_keys_id_(media_keys_id),
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif  // defined(ENABLE_PEPPER_CDMS)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      key_added_cb_(key_added_cb),
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      key_error_cb_(key_error_cb),
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      key_message_cb_(key_message_cb) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyDecryptor::~ProxyDecryptor() {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Destroy the decryptor explicitly before destroying the plugin.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    media_keys_.reset();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xhwang): Support multiple decryptor notification request (e.g. from
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// video and audio decoders). The current implementation is okay for the current
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// media pipeline since we initialize audio and video decoders in sequence.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// But ProxyDecryptor should not depend on media pipeline's implementation
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// detail.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyDecryptor::SetDecryptorReadyCB(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     const media::DecryptorReadyCB& decryptor_ready_cb) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancels the previous decryptor request.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (decryptor_ready_cb.is_null()) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!decryptor_ready_cb_.is_null())
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::ResetAndReturn(&decryptor_ready_cb_).Run(NULL);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Normal decryptor request.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(decryptor_ready_cb_.is_null());
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (media_keys_) {
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    decryptor_ready_cb.Run(media_keys_->GetDecryptor());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decryptor_ready_cb_ = decryptor_ready_cb;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool ProxyDecryptor::InitializeCDM(const std::string& key_system) {
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DVLOG(1) << "InitializeCDM: key_system = " << key_system;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!media_keys_);
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  media_keys_ = CreateMediaKeys(key_system);
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return media_keys_ != NULL;
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool ProxyDecryptor::GenerateKeyRequest(const std::string& type,
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                        const uint8* init_data,
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                        int init_data_length) {
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!media_keys_->GenerateKeyRequest(type, init_data, init_data_length)) {
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    media_keys_.reset();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!decryptor_ready_cb_.is_null())
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::ResetAndReturn(&decryptor_ready_cb_).Run(media_keys_->GetDecryptor());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::AddKey(const uint8* key,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            int key_length,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const uint8* init_data,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            int init_data_length,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& session_id) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "AddKey()";
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  media_keys_->AddKey(key, key_length, init_data, init_data_length, session_id);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "CancelKeyRequest()";
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  media_keys_->CancelKeyRequest(session_id);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& key_system) {
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return ContentDecryptionModuleFactory::Create(
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      key_system,
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS)
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_media_player_client_,
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_frame_,
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&ProxyDecryptor::DestroyHelperPlugin,
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 weak_ptr_factory_.GetWeakPtr()),
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#elif defined(OS_ANDROID)
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      proxy_,
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      media_keys_id_,
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif  // defined(ENABLE_PEPPER_CDMS)
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&ProxyDecryptor::KeyAdded, weak_ptr_factory_.GetWeakPtr()),
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&ProxyDecryptor::KeyError, weak_ptr_factory_.GetWeakPtr()),
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&ProxyDecryptor::KeyMessage, weak_ptr_factory_.GetWeakPtr()));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::KeyAdded(const std::string& session_id) {
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  key_added_cb_.Run(session_id);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::KeyError(const std::string& session_id,
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              media::MediaKeys::KeyError error_code,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              int system_code) {
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  key_error_cb_.Run(session_id, error_code, system_code);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::KeyMessage(const std::string& session_id,
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                const std::vector<uint8>& message,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const std::string& default_url) {
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  key_message_cb_.Run(session_id, message, default_url);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace content
156