proxy_decryptor.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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.
4
5#include "content/renderer/media/crypto/proxy_decryptor.h"
6
7#include "base/bind.h"
8#include "base/callback_helpers.h"
9#include "base/logging.h"
10#include "content/renderer/media/crypto/content_decryption_module_factory.h"
11
12namespace content {
13
14#if defined(ENABLE_PEPPER_CDMS)
15void ProxyDecryptor::DestroyHelperPlugin() {
16  ContentDecryptionModuleFactory::DestroyHelperPlugin(
17      web_media_player_client_, web_frame_);
18}
19#endif  // defined(ENABLE_PEPPER_CDMS)
20
21ProxyDecryptor::ProxyDecryptor(
22#if defined(ENABLE_PEPPER_CDMS)
23    WebKit::WebMediaPlayerClient* web_media_player_client,
24    WebKit::WebFrame* web_frame,
25#elif defined(OS_ANDROID)
26    WebMediaPlayerProxyAndroid* proxy,
27    int media_keys_id,
28#endif  // defined(ENABLE_PEPPER_CDMS)
29    const media::KeyAddedCB& key_added_cb,
30    const media::KeyErrorCB& key_error_cb,
31    const media::KeyMessageCB& key_message_cb)
32    : weak_ptr_factory_(this),
33#if defined(ENABLE_PEPPER_CDMS)
34      web_media_player_client_(web_media_player_client),
35      web_frame_(web_frame),
36#elif defined(OS_ANDROID)
37      proxy_(proxy),
38      media_keys_id_(media_keys_id),
39#endif  // defined(ENABLE_PEPPER_CDMS)
40      key_added_cb_(key_added_cb),
41      key_error_cb_(key_error_cb),
42      key_message_cb_(key_message_cb) {
43}
44
45ProxyDecryptor::~ProxyDecryptor() {
46  // Destroy the decryptor explicitly before destroying the plugin.
47  {
48    base::AutoLock auto_lock(lock_);
49    media_keys_.reset();
50  }
51}
52
53// TODO(xhwang): Support multiple decryptor notification request (e.g. from
54// video and audio decoders). The current implementation is okay for the current
55// media pipeline since we initialize audio and video decoders in sequence.
56// But ProxyDecryptor should not depend on media pipeline's implementation
57// detail.
58void ProxyDecryptor::SetDecryptorReadyCB(
59     const media::DecryptorReadyCB& decryptor_ready_cb) {
60  base::AutoLock auto_lock(lock_);
61
62  // Cancels the previous decryptor request.
63  if (decryptor_ready_cb.is_null()) {
64    if (!decryptor_ready_cb_.is_null())
65      base::ResetAndReturn(&decryptor_ready_cb_).Run(NULL);
66    return;
67  }
68
69  // Normal decryptor request.
70  DCHECK(decryptor_ready_cb_.is_null());
71  if (media_keys_) {
72    decryptor_ready_cb.Run(media_keys_->GetDecryptor());
73    return;
74  }
75  decryptor_ready_cb_ = decryptor_ready_cb;
76}
77
78bool ProxyDecryptor::InitializeCDM(const std::string& key_system,
79                                   const GURL& frame_url) {
80  DVLOG(1) << "InitializeCDM: key_system = " << key_system;
81
82  base::AutoLock auto_lock(lock_);
83
84  DCHECK(!media_keys_);
85  media_keys_ = CreateMediaKeys(key_system, frame_url);
86  if (!media_keys_)
87    return false;
88
89  if (!decryptor_ready_cb_.is_null())
90    base::ResetAndReturn(&decryptor_ready_cb_).Run(media_keys_->GetDecryptor());
91  return true;
92}
93
94bool ProxyDecryptor::GenerateKeyRequest(const std::string& type,
95                                        const uint8* init_data,
96                                        int init_data_length) {
97  if (!media_keys_->GenerateKeyRequest(type, init_data, init_data_length)) {
98    media_keys_.reset();
99    return false;
100  }
101
102  return true;
103}
104
105void ProxyDecryptor::AddKey(const uint8* key,
106                            int key_length,
107                            const uint8* init_data,
108                            int init_data_length,
109                            const std::string& session_id) {
110  DVLOG(1) << "AddKey()";
111
112  // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
113  media_keys_->AddKey(key, key_length, init_data, init_data_length, session_id);
114}
115
116void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) {
117  DVLOG(1) << "CancelKeyRequest()";
118
119  // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
120  media_keys_->CancelKeyRequest(session_id);
121}
122
123scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys(
124    const std::string& key_system,
125    const GURL& frame_url) {
126  return ContentDecryptionModuleFactory::Create(
127      key_system,
128#if defined(ENABLE_PEPPER_CDMS)
129      web_media_player_client_,
130      web_frame_,
131      base::Bind(&ProxyDecryptor::DestroyHelperPlugin,
132                 weak_ptr_factory_.GetWeakPtr()),
133#elif defined(OS_ANDROID)
134      proxy_,
135      media_keys_id_,
136      frame_url,
137#endif  // defined(ENABLE_PEPPER_CDMS)
138      base::Bind(&ProxyDecryptor::KeyAdded, weak_ptr_factory_.GetWeakPtr()),
139      base::Bind(&ProxyDecryptor::KeyError, weak_ptr_factory_.GetWeakPtr()),
140      base::Bind(&ProxyDecryptor::KeyMessage, weak_ptr_factory_.GetWeakPtr()));
141}
142
143void ProxyDecryptor::KeyAdded(const std::string& session_id) {
144  key_added_cb_.Run(session_id);
145}
146
147void ProxyDecryptor::KeyError(const std::string& session_id,
148                              media::MediaKeys::KeyError error_code,
149                              int system_code) {
150  key_error_cb_.Run(session_id, error_code, system_code);
151}
152
153void ProxyDecryptor::KeyMessage(const std::string& session_id,
154                                const std::vector<uint8>& message,
155                                const std::string& default_url) {
156  key_message_cb_.Run(session_id, message, default_url);
157}
158
159}  // namespace content
160