Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: webkit/media/crypto/proxy_decryptor.cc

Issue 10822026: Implement "Key Presence" step in "Encrypted Block Encounted" algorithm in EME. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use message_loop_proxy. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/media/crypto/proxy_decryptor.h" 5 #include "webkit/media/crypto/proxy_decryptor.h"
6 6
7 #include "base/bind.h"
8 #include "base/location.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop_proxy.h"
8 #include "media/base/decoder_buffer.h" 11 #include "media/base/decoder_buffer.h"
9 #include "media/base/decryptor_client.h" 12 #include "media/base/decryptor_client.h"
10 #include "media/crypto/aes_decryptor.h" 13 #include "media/crypto/aes_decryptor.h"
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" 15 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
13 #include "webkit/media/crypto/key_systems.h" 16 #include "webkit/media/crypto/key_systems.h"
14 #include "webkit/media/crypto/ppapi_decryptor.h" 17 #include "webkit/media/crypto/ppapi_decryptor.h"
15 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 18 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
16 #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h" 19 #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
17 // TODO(xhwang): Put this include after "ppapi_plugin_instance.h" for definition 20 // TODO(xhwang): Put this include after "ppapi_plugin_instance.h" for definition
18 // of "uint8_t", which WebMediaPlayer.h uses without including a header for it. 21 // of "uint8_t", which WebMediaPlayer.h uses without including a header for it.
19 // See: https://bugs.webkit.org/show_bug.cgi?id=92031 22 // See: https://bugs.webkit.org/show_bug.cgi?id=92031
20 // Fix include order here when the bug is fixed. 23 // Fix include order here when the bug is fixed.
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient. h" 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient. h"
22 25
26 using media::Decryptor;
27 using media::DecoderBuffer;
28
23 namespace webkit_media { 29 namespace webkit_media {
24 30
25 static scoped_refptr<webkit::ppapi::PluginInstance> CreatePluginInstance( 31 static scoped_refptr<webkit::ppapi::PluginInstance> CreatePluginInstance(
26 const std::string& plugin_type, 32 const std::string& plugin_type,
27 WebKit::WebMediaPlayerClient* web_media_player_client, 33 WebKit::WebMediaPlayerClient* web_media_player_client,
28 WebKit::WebFrame* web_frame) { 34 WebKit::WebFrame* web_frame) {
29 DCHECK(web_media_player_client); 35 DCHECK(web_media_player_client);
30 DCHECK(web_frame); 36 DCHECK(web_frame);
31 37
32 WebKit::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin( 38 WebKit::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin(
33 WebKit::WebString::fromUTF8(plugin_type), web_frame); 39 WebKit::WebString::fromUTF8(plugin_type), web_frame);
34 if (!web_plugin) 40 if (!web_plugin)
35 return NULL; 41 return NULL;
36 42
37 DCHECK(!web_plugin->isPlaceholder()); // Prevented by WebKit. 43 DCHECK(!web_plugin->isPlaceholder()); // Prevented by WebKit.
38 // Only Pepper plugins are supported, so it must be a ppapi object. 44 // Only Pepper plugins are supported, so it must be a ppapi object.
39 webkit::ppapi::WebPluginImpl* ppapi_plugin = 45 webkit::ppapi::WebPluginImpl* ppapi_plugin =
40 static_cast<webkit::ppapi::WebPluginImpl*>(web_plugin); 46 static_cast<webkit::ppapi::WebPluginImpl*>(web_plugin);
41 return ppapi_plugin->instance(); 47 return ppapi_plugin->instance();
42 } 48 }
43 49
50 // TODO(xhwang): Simplify this function. This is mostly caused by the fact that
51 // we need to copy a scoped_array<uint8>.
52 static void FireNeedKey(media::DecryptorClient* client,
53 const scoped_refptr<DecoderBuffer>& encrypted) {
54 DCHECK(client);
55 DCHECK(encrypted);
56 DCHECK(encrypted->GetDecryptConfig());
57 const uint8* key_id = encrypted->GetDecryptConfig()->key_id();
58 const int key_id_size = encrypted->GetDecryptConfig()->key_id_size();
59 scoped_array<uint8> key_id_array(new uint8[key_id_size]);
60 memcpy(key_id_array.get(), key_id, key_id_size);
61 client->NeedKey("", "", key_id_array.Pass(), key_id_size);
62 }
63
44 ProxyDecryptor::ProxyDecryptor( 64 ProxyDecryptor::ProxyDecryptor(
45 media::DecryptorClient* decryptor_client, 65 media::DecryptorClient* decryptor_client,
46 WebKit::WebMediaPlayerClient* web_media_player_client, 66 WebKit::WebMediaPlayerClient* web_media_player_client,
47 WebKit::WebFrame* web_frame) 67 WebKit::WebFrame* web_frame)
48 : client_(decryptor_client), 68 : client_(decryptor_client),
49 web_media_player_client_(web_media_player_client), 69 web_media_player_client_(web_media_player_client),
50 web_frame_(web_frame) { 70 web_frame_(web_frame) {
51 } 71 }
52 72
53 ProxyDecryptor::~ProxyDecryptor() { 73 ProxyDecryptor::~ProxyDecryptor() {
54 } 74 }
55 75
56 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system, 76 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system,
57 const uint8* init_data, 77 const uint8* init_data,
58 int init_data_length) { 78 int init_data_length) {
59 // We do not support run-time switching of decryptors. GenerateKeyRequest() 79 // We do not support run-time switching of decryptors. GenerateKeyRequest()
60 // only creates a new decryptor when |decryptor_| is not initialized. 80 // only creates a new decryptor when |decryptor_| is not initialized.
81 DVLOG(1) << "GenerateKeyRequest: key_system = " << key_system;
61 if (!decryptor_.get()) { 82 if (!decryptor_.get()) {
62 base::AutoLock auto_lock(lock_); 83 base::AutoLock auto_lock(decryptor_lock_);
63 decryptor_ = CreateDecryptor(key_system); 84 decryptor_ = CreateDecryptor(key_system);
64 } 85 }
65 86
66 DCHECK(client_);
67 if (!decryptor_.get()) { 87 if (!decryptor_.get()) {
68 client_->KeyError(key_system, "", media::Decryptor::kUnknownError, 0); 88 DCHECK(client_);
scherkus (not reviewing) 2012/07/26 02:06:38 dcheck not needed
xhwang 2012/07/26 22:16:04 Done.
89 client_->KeyError(key_system, "", Decryptor::kUnknownError, 0);
69 return; 90 return;
70 } 91 }
71 92
72 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length); 93 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length);
73 } 94 }
74 95
75 void ProxyDecryptor::AddKey(const std::string& key_system, 96 void ProxyDecryptor::AddKey(const std::string& key_system,
76 const uint8* key, 97 const uint8* key,
77 int key_length, 98 int key_length,
78 const uint8* init_data, 99 const uint8* init_data,
79 int init_data_length, 100 int init_data_length,
80 const std::string& session_id) { 101 const std::string& session_id) {
102 DVLOG(1) << "AddKey()";
103
81 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. 104 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
82 DCHECK(decryptor_.get()); 105 DCHECK(decryptor_.get());
83 decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length, 106 decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length,
84 session_id); 107 session_id);
108
109 std::vector<base::Closure> closures_to_run;
110 {
111 base::AutoLock auto_lock(pending_decrypt_closures_lock_);
112 std::swap(pending_decrypt_closures_, closures_to_run);
113 }
114
115 for (std::vector<base::Closure>::iterator iter = closures_to_run.begin();
116 iter != closures_to_run.end();
117 ++iter) {
118 iter->Run();
119 }
85 } 120 }
86 121
87 void ProxyDecryptor::CancelKeyRequest(const std::string& key_system, 122 void ProxyDecryptor::CancelKeyRequest(const std::string& key_system,
88 const std::string& session_id) { 123 const std::string& session_id) {
124 DVLOG(1) << "CancelKeyRequest()";
125
89 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. 126 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
90 DCHECK(decryptor_.get()); 127 DCHECK(decryptor_.get());
91 decryptor_->CancelKeyRequest(key_system, session_id); 128 decryptor_->CancelKeyRequest(key_system, session_id);
92 } 129 }
93 130
94 void ProxyDecryptor::Decrypt( 131 void ProxyDecryptor::Decrypt(
95 const scoped_refptr<media::DecoderBuffer>& encrypted, 132 const scoped_refptr<DecoderBuffer>& encrypted,
96 const DecryptCB& decrypt_cb) { 133 const DecryptCB& decrypt_cb) {
134 DVLOG(2) << "Decrypt()";
135
97 // This is safe as we do not replace/delete an existing decryptor at run-time. 136 // This is safe as we do not replace/delete an existing decryptor at run-time.
98 media::Decryptor* decryptor = NULL; 137 Decryptor* decryptor = NULL;
99 { 138 {
100 base::AutoLock auto_lock(lock_); 139 base::AutoLock auto_lock(decryptor_lock_);
101 decryptor = decryptor_.get(); 140 decryptor = decryptor_.get();
102 } 141 }
142
103 if (!decryptor) { 143 if (!decryptor) {
104 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized."; 144 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized.";
105 decrypt_cb.Run(kError, NULL); 145 {
146 base::AutoLock auto_lock(pending_decrypt_closures_lock_);
147 pending_decrypt_closures_.push_back(base::Bind(
148 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
149 base::MessageLoopProxy::current(), encrypted, decrypt_cb));
150 }
151 // TODO(xhwang): The same NeedKey may be fired here and multiple times in
152 // OnBufferDecrypted(). While the spec says only one NeedKey should be
153 // fired. Leave them as is since the spec about this may change.
154 FireNeedKey(client_, encrypted);
106 return; 155 return;
107 } 156 }
108 157
109 decryptor->Decrypt(encrypted, decrypt_cb); 158 decryptor->Decrypt(encrypted, base::Bind(
159 &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this),
160 base::MessageLoopProxy::current(), encrypted, decrypt_cb));
110 } 161 }
111 162
112 scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor( 163 scoped_ptr<Decryptor> ProxyDecryptor::CreatePpapiDecryptor(
113 const std::string& key_system) { 164 const std::string& key_system) {
114 DCHECK(client_); 165 DCHECK(client_);
115 DCHECK(web_media_player_client_); 166 DCHECK(web_media_player_client_);
116 DCHECK(web_frame_); 167 DCHECK(web_frame_);
117 168
118 std::string plugin_type = GetPluginType(key_system); 169 std::string plugin_type = GetPluginType(key_system);
119 DCHECK(!plugin_type.empty()); 170 DCHECK(!plugin_type.empty());
120 const scoped_refptr<webkit::ppapi::PluginInstance>& plugin_instance = 171 const scoped_refptr<webkit::ppapi::PluginInstance>& plugin_instance =
121 CreatePluginInstance(plugin_type, web_media_player_client_, web_frame_); 172 CreatePluginInstance(plugin_type, web_media_player_client_, web_frame_);
122 if (!plugin_instance) { 173 if (!plugin_instance) {
123 DVLOG(1) << "PpapiDecryptor: plugin instance creation failed."; 174 DVLOG(1) << "PpapiDecryptor: plugin instance creation failed.";
124 return scoped_ptr<media::Decryptor>(); 175 return scoped_ptr<Decryptor>();
125 } 176 }
126 177
127 return scoped_ptr<media::Decryptor>(new PpapiDecryptor(client_, 178 return scoped_ptr<Decryptor>(new PpapiDecryptor(client_, plugin_instance));
128 plugin_instance));
129 } 179 }
130 180
131 scoped_ptr<media::Decryptor> ProxyDecryptor::CreateDecryptor( 181 scoped_ptr<Decryptor> ProxyDecryptor::CreateDecryptor(
132 const std::string& key_system) { 182 const std::string& key_system) {
133 DCHECK(client_); 183 DCHECK(client_);
134 184
135 if (CanUseAesDecryptor(key_system)) 185 if (CanUseAesDecryptor(key_system))
136 return scoped_ptr<media::Decryptor>(new media::AesDecryptor(client_)); 186 return scoped_ptr<Decryptor>(new media::AesDecryptor(client_));
137 187
138 // We only support AesDecryptor and PpapiDecryptor. So if we cannot 188 // We only support AesDecryptor and PpapiDecryptor. So if we cannot
139 // use the AesDecryptor, then we'll try to create a PpapiDecryptor for given 189 // use the AesDecryptor, then we'll try to create a PpapiDecryptor for given
140 // |key_system|. 190 // |key_system|.
141 return CreatePpapiDecryptor(key_system); 191 return CreatePpapiDecryptor(key_system);
142 } 192 }
143 193
194 void ProxyDecryptor::DecryptOnMessageLoop(
195 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
196 const scoped_refptr<DecoderBuffer>& encrypted,
197 const Decryptor::DecryptCB& decrypt_cb) {
198 DVLOG(2) << "DecryptOnMessageLoop()";
199 DCHECK(decryptor_.get());
200
201 if (!message_loop_proxy->BelongsToCurrentThread()) {
202 message_loop_proxy->PostTask(FROM_HERE, base::Bind(
203 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
204 message_loop_proxy, encrypted, decrypt_cb));
205 return;
206 }
207
208 decryptor_->Decrypt(encrypted, base::Bind(&ProxyDecryptor::OnBufferDecrypted,
209 base::Unretained(this), message_loop_proxy, encrypted, decrypt_cb));
210 }
211
212 void ProxyDecryptor::OnBufferDecrypted(
213 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
214 const scoped_refptr<DecoderBuffer>& encrypted,
215 const Decryptor::DecryptCB& decrypt_cb,
216 Decryptor::DecryptStatus status,
217 const scoped_refptr<DecoderBuffer>& decrypted) {
218 DVLOG(2) << "OnBufferDecrypted()";
219
220 if (status == Decryptor::kSuccess || status == Decryptor::kError) {
221 decrypt_cb.Run(status, decrypted);
222 return;
223 }
224
225 DCHECK_EQ(status, Decryptor::kNoKey);
226 DVLOG(1) << "OnBufferDecrypted(): kNoKey fired";
227 {
228 base::AutoLock auto_lock(pending_decrypt_closures_lock_);
229 pending_decrypt_closures_.push_back(base::Bind(
230 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
231 message_loop_proxy, encrypted, decrypt_cb));
232 }
233 // TODO(xhwang): The same NeedKey may be fired multiple times here and also
234 // in Decrypt(). While the spec says only one NeedKey should be fired. Leave
235 // them as is since the spec about this may change.
236 FireNeedKey(client_, encrypted);
237 }
238
144 } // namespace webkit_media 239 } // namespace webkit_media
OLDNEW
« webkit/media/crypto/proxy_decryptor.h ('K') | « webkit/media/crypto/proxy_decryptor.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698