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

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: Rebase 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 <algorithm>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/location.h" 10 #include "base/location.h"
9 #include "base/logging.h" 11 #include "base/logging.h"
10 #include "base/message_loop_proxy.h" 12 #include "base/message_loop_proxy.h"
11 #include "media/base/decoder_buffer.h" 13 #include "media/base/decoder_buffer.h"
12 #include "media/base/decryptor_client.h" 14 #include "media/base/decryptor_client.h"
13 #include "media/crypto/aes_decryptor.h" 15 #include "media/crypto/aes_decryptor.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" 17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
16 #include "webkit/media/crypto/key_systems.h" 18 #include "webkit/media/crypto/key_systems.h"
17 #include "webkit/media/crypto/ppapi_decryptor.h" 19 #include "webkit/media/crypto/ppapi_decryptor.h"
18 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 20 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
19 #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h" 21 #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
20 // TODO(xhwang): Put this include after "ppapi_plugin_instance.h" for definition 22 // TODO(xhwang): Put this include after "ppapi_plugin_instance.h" for definition
21 // of "uint8_t", which WebMediaPlayer.h uses without including a header for it. 23 // of "uint8_t", which WebMediaPlayer.h uses without including a header for it.
22 // See: https://bugs.webkit.org/show_bug.cgi?id=92031 24 // See: https://bugs.webkit.org/show_bug.cgi?id=92031
23 // Fix include order here when the bug is fixed. 25 // Fix include order here when the bug is fixed.
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient. h" 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient. h"
25 27
26 using media::Decryptor;
27 using media::DecoderBuffer;
28
29 namespace webkit_media { 28 namespace webkit_media {
30 29
31 static scoped_refptr<webkit::ppapi::PluginInstance> CreatePluginInstance( 30 static scoped_refptr<webkit::ppapi::PluginInstance> CreatePluginInstance(
32 const std::string& plugin_type, 31 const std::string& plugin_type,
33 WebKit::WebMediaPlayerClient* web_media_player_client, 32 WebKit::WebMediaPlayerClient* web_media_player_client,
34 WebKit::WebFrame* web_frame) { 33 WebKit::WebFrame* web_frame) {
35 DCHECK(web_media_player_client); 34 DCHECK(web_media_player_client);
36 DCHECK(web_frame); 35 DCHECK(web_frame);
37 36
38 WebKit::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin( 37 WebKit::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin(
39 WebKit::WebString::fromUTF8(plugin_type), web_frame); 38 WebKit::WebString::fromUTF8(plugin_type), web_frame);
40 if (!web_plugin) 39 if (!web_plugin)
41 return NULL; 40 return NULL;
42 41
43 DCHECK(!web_plugin->isPlaceholder()); // Prevented by WebKit. 42 DCHECK(!web_plugin->isPlaceholder()); // Prevented by WebKit.
44 // Only Pepper plugins are supported, so it must be a ppapi object. 43 // Only Pepper plugins are supported, so it must be a ppapi object.
45 webkit::ppapi::WebPluginImpl* ppapi_plugin = 44 webkit::ppapi::WebPluginImpl* ppapi_plugin =
46 static_cast<webkit::ppapi::WebPluginImpl*>(web_plugin); 45 static_cast<webkit::ppapi::WebPluginImpl*>(web_plugin);
47 return ppapi_plugin->instance(); 46 return ppapi_plugin->instance();
48 } 47 }
49 48
50 // TODO(xhwang): Simplify this function. This is mostly caused by the fact that 49 // TODO(xhwang): Simplify this function. This is mostly caused by the fact that
51 // we need to copy a scoped_array<uint8>. 50 // we need to copy a scoped_array<uint8>.
52 static void FireNeedKey(media::DecryptorClient* client, 51 static void FireNeedKey(media::DecryptorClient* client,
53 const scoped_refptr<DecoderBuffer>& encrypted) { 52 const scoped_refptr<media::DecoderBuffer>& encrypted) {
54 DCHECK(client); 53 DCHECK(client);
55 DCHECK(encrypted); 54 DCHECK(encrypted);
56 DCHECK(encrypted->GetDecryptConfig()); 55 DCHECK(encrypted->GetDecryptConfig());
57 const uint8* key_id = encrypted->GetDecryptConfig()->key_id(); 56 std::string key_id = encrypted->GetDecryptConfig()->key_id();
58 const int key_id_size = encrypted->GetDecryptConfig()->key_id_size(); 57 scoped_array<uint8> key_id_array(new uint8[key_id.size()]);
59 scoped_array<uint8> key_id_array(new uint8[key_id_size]); 58 memcpy(key_id_array.get(), key_id.data(), key_id.size());
60 memcpy(key_id_array.get(), key_id, key_id_size); 59 client->NeedKey("", "", key_id_array.Pass(), key_id.size());
61 client->NeedKey("", "", key_id_array.Pass(), key_id_size);
62 } 60 }
63 61
64 ProxyDecryptor::ProxyDecryptor( 62 ProxyDecryptor::ProxyDecryptor(
65 media::DecryptorClient* decryptor_client, 63 media::DecryptorClient* decryptor_client,
66 WebKit::WebMediaPlayerClient* web_media_player_client, 64 WebKit::WebMediaPlayerClient* web_media_player_client,
67 WebKit::WebFrame* web_frame) 65 WebKit::WebFrame* web_frame)
68 : client_(decryptor_client), 66 : client_(decryptor_client),
69 web_media_player_client_(web_media_player_client), 67 web_media_player_client_(web_media_player_client),
70 web_frame_(web_frame) { 68 web_frame_(web_frame),
69 is_shutting_down_(false) {
71 } 70 }
72 71
73 ProxyDecryptor::~ProxyDecryptor() { 72 ProxyDecryptor::~ProxyDecryptor() {
74 } 73 }
75 74
76 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system, 75 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system,
77 const uint8* init_data, 76 const uint8* init_data,
78 int init_data_length) { 77 int init_data_length) {
79 // We do not support run-time switching of decryptors. GenerateKeyRequest() 78 // We do not support run-time switching of decryptors. GenerateKeyRequest()
80 // only creates a new decryptor when |decryptor_| is not initialized. 79 // only creates a new decryptor when |decryptor_| is not initialized.
81 DVLOG(1) << "GenerateKeyRequest: key_system = " << key_system; 80 DVLOG(1) << "GenerateKeyRequest: key_system = " << key_system;
82 if (!decryptor_.get()) { 81 if (!decryptor_.get()) {
83 base::AutoLock auto_lock(decryptor_lock_); 82 base::AutoLock auto_lock(lock_);
84 decryptor_ = CreateDecryptor(key_system); 83 decryptor_ = CreateDecryptor(key_system);
85 } 84 }
86 85
87 if (!decryptor_.get()) { 86 if (!decryptor_.get()) {
88 DCHECK(client_); 87 client_->KeyError(key_system, "", media::Decryptor::kUnknownError, 0);
89 client_->KeyError(key_system, "", Decryptor::kUnknownError, 0);
90 return; 88 return;
91 } 89 }
92 90
93 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length); 91 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length);
94 } 92 }
95 93
96 void ProxyDecryptor::AddKey(const std::string& key_system, 94 void ProxyDecryptor::AddKey(const std::string& key_system,
97 const uint8* key, 95 const uint8* key,
98 int key_length, 96 int key_length,
99 const uint8* init_data, 97 const uint8* init_data,
100 int init_data_length, 98 int init_data_length,
101 const std::string& session_id) { 99 const std::string& session_id) {
102 DVLOG(1) << "AddKey()"; 100 DVLOG(1) << "AddKey()";
103 101
104 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. 102 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
105 DCHECK(decryptor_.get()); 103 DCHECK(decryptor_.get());
106 decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length, 104 decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length,
107 session_id); 105 session_id);
108 106
109 std::vector<base::Closure> closures_to_run; 107 std::vector<base::Closure> closures_to_run;
110 { 108 {
111 base::AutoLock auto_lock(pending_decrypt_closures_lock_); 109 base::AutoLock auto_lock(lock_);
112 std::swap(pending_decrypt_closures_, closures_to_run); 110 std::swap(pending_decrypt_closures_, closures_to_run);
113 } 111 }
114 112
113 // Fire all pending callbacks here because only the |decryptor_| knows if the
114 // pending buffers can be decrypted or not.
115 for (std::vector<base::Closure>::iterator iter = closures_to_run.begin(); 115 for (std::vector<base::Closure>::iterator iter = closures_to_run.begin();
116 iter != closures_to_run.end(); 116 iter != closures_to_run.end();
117 ++iter) { 117 ++iter) {
118 iter->Run(); 118 iter->Run();
119 } 119 }
120 } 120 }
121 121
122 void ProxyDecryptor::CancelKeyRequest(const std::string& key_system, 122 void ProxyDecryptor::CancelKeyRequest(const std::string& key_system,
123 const std::string& session_id) { 123 const std::string& session_id) {
124 DVLOG(1) << "CancelKeyRequest()"; 124 DVLOG(1) << "CancelKeyRequest()";
125 125
126 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. 126 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
127 DCHECK(decryptor_.get()); 127 DCHECK(decryptor_.get());
128 decryptor_->CancelKeyRequest(key_system, session_id); 128 decryptor_->CancelKeyRequest(key_system, session_id);
129 } 129 }
130 130
131 void ProxyDecryptor::Decrypt( 131 void ProxyDecryptor::Decrypt(
132 const scoped_refptr<DecoderBuffer>& encrypted, 132 const scoped_refptr<media::DecoderBuffer>& encrypted,
133 const DecryptCB& decrypt_cb) { 133 const DecryptCB& decrypt_cb) {
134 DVLOG(2) << "Decrypt()";
135
136 // This is safe as we do not replace/delete an existing decryptor at run-time. 134 // This is safe as we do not replace/delete an existing decryptor at run-time.
137 Decryptor* decryptor = NULL; 135 media::Decryptor* decryptor = NULL;
138 { 136 {
139 base::AutoLock auto_lock(decryptor_lock_); 137 base::AutoLock auto_lock(lock_);
138 if (is_shutting_down_) {
139 DVLOG(1) << "Decrypt(): fire decrypt callbacks with kError.";
140 decrypt_cb.Run(kError, NULL);
141 return;
142 }
140 decryptor = decryptor_.get(); 143 decryptor = decryptor_.get();
141 } 144 if (!decryptor) {
142 145 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized.";
143 if (!decryptor) { 146 pending_decrypt_closures_.push_back(
144 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized."; 147 base::Bind(&ProxyDecryptor::DecryptOnMessageLoop,
145 { 148 base::Unretained(this),
146 base::AutoLock auto_lock(pending_decrypt_closures_lock_); 149 base::MessageLoopProxy::current(), encrypted,
147 pending_decrypt_closures_.push_back(base::Bind( 150 decrypt_cb));
148 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this), 151 // TODO(xhwang): The same NeedKey may be fired here and multiple times in
149 base::MessageLoopProxy::current(), encrypted, decrypt_cb)); 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);
155 return;
150 } 156 }
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);
155 return;
156 } 157 }
157 158
158 decryptor->Decrypt(encrypted, base::Bind( 159 decryptor->Decrypt(encrypted, base::Bind(
159 &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this), 160 &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this),
160 base::MessageLoopProxy::current(), encrypted, decrypt_cb)); 161 base::MessageLoopProxy::current(), encrypted, decrypt_cb));
161 } 162 }
162 163
163 scoped_ptr<Decryptor> ProxyDecryptor::CreatePpapiDecryptor( 164 void ProxyDecryptor::Stop() {
165 DVLOG(1) << "AddKey()";
166
167 std::vector<base::Closure> closures_to_run;
168 {
169 base::AutoLock auto_lock(lock_);
170 if (decryptor_.get())
171 decryptor_->Stop();
172 is_shutting_down_ = true;
173 std::swap(pending_decrypt_closures_, closures_to_run);
174 }
175
176 for (std::vector<base::Closure>::iterator iter = closures_to_run.begin();
177 iter != closures_to_run.end();
178 ++iter) {
179 iter->Run();
180 }
181 }
182
183 scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor(
164 const std::string& key_system) { 184 const std::string& key_system) {
165 DCHECK(client_); 185 DCHECK(client_);
166 DCHECK(web_media_player_client_); 186 DCHECK(web_media_player_client_);
167 DCHECK(web_frame_); 187 DCHECK(web_frame_);
168 188
169 std::string plugin_type = GetPluginType(key_system); 189 std::string plugin_type = GetPluginType(key_system);
170 DCHECK(!plugin_type.empty()); 190 DCHECK(!plugin_type.empty());
171 const scoped_refptr<webkit::ppapi::PluginInstance>& plugin_instance = 191 const scoped_refptr<webkit::ppapi::PluginInstance>& plugin_instance =
172 CreatePluginInstance(plugin_type, web_media_player_client_, web_frame_); 192 CreatePluginInstance(plugin_type, web_media_player_client_, web_frame_);
173 if (!plugin_instance) { 193 if (!plugin_instance) {
174 DVLOG(1) << "PpapiDecryptor: plugin instance creation failed."; 194 DVLOG(1) << "PpapiDecryptor: plugin instance creation failed.";
175 return scoped_ptr<Decryptor>(); 195 return scoped_ptr<media::Decryptor>();
176 } 196 }
177 197
178 return scoped_ptr<Decryptor>(new PpapiDecryptor(client_, plugin_instance)); 198 return scoped_ptr<media::Decryptor>(new PpapiDecryptor(client_,
199 plugin_instance));
179 } 200 }
180 201
181 scoped_ptr<Decryptor> ProxyDecryptor::CreateDecryptor( 202 scoped_ptr<media::Decryptor> ProxyDecryptor::CreateDecryptor(
182 const std::string& key_system) { 203 const std::string& key_system) {
183 DCHECK(client_); 204 DCHECK(client_);
184 205
185 if (CanUseAesDecryptor(key_system)) 206 if (CanUseAesDecryptor(key_system))
186 return scoped_ptr<Decryptor>(new media::AesDecryptor(client_)); 207 return scoped_ptr<media::Decryptor>(new media::AesDecryptor(client_));
187 208
188 // We only support AesDecryptor and PpapiDecryptor. So if we cannot 209 // We only support AesDecryptor and PpapiDecryptor. So if we cannot
189 // use the AesDecryptor, then we'll try to create a PpapiDecryptor for given 210 // use the AesDecryptor, then we'll try to create a PpapiDecryptor for given
190 // |key_system|. 211 // |key_system|.
191 return CreatePpapiDecryptor(key_system); 212 return CreatePpapiDecryptor(key_system);
192 } 213 }
193 214
194 void ProxyDecryptor::DecryptOnMessageLoop( 215 void ProxyDecryptor::DecryptOnMessageLoop(
195 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, 216 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
196 const scoped_refptr<DecoderBuffer>& encrypted, 217 const scoped_refptr<media::DecoderBuffer>& encrypted,
197 const Decryptor::DecryptCB& decrypt_cb) { 218 const media::Decryptor::DecryptCB& decrypt_cb) {
198 DVLOG(2) << "DecryptOnMessageLoop()";
199 DCHECK(decryptor_.get()); 219 DCHECK(decryptor_.get());
200 220
201 if (!message_loop_proxy->BelongsToCurrentThread()) { 221 if (!message_loop_proxy->BelongsToCurrentThread()) {
202 message_loop_proxy->PostTask(FROM_HERE, base::Bind( 222 message_loop_proxy->PostTask(FROM_HERE, base::Bind(
203 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this), 223 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
204 message_loop_proxy, encrypted, decrypt_cb)); 224 message_loop_proxy, encrypted, decrypt_cb));
205 return; 225 return;
206 } 226 }
207 227
228 {
229 base::AutoLock auto_lock(lock_);
230 if (is_shutting_down_) {
231 DVLOG(1) << "DecryptOnMessageLoop(): fire decrypt callbacks with kError.";
232 decrypt_cb.Run(kError, NULL);
233 return;
234 }
235 }
236
208 decryptor_->Decrypt(encrypted, base::Bind(&ProxyDecryptor::OnBufferDecrypted, 237 decryptor_->Decrypt(encrypted, base::Bind(&ProxyDecryptor::OnBufferDecrypted,
scherkus (not reviewing) 2012/08/02 18:05:32 nit: technically this is mixing style: params on n
xhwang 2012/08/03 20:08:10 Done.
209 base::Unretained(this), message_loop_proxy, encrypted, decrypt_cb)); 238 base::Unretained(this), message_loop_proxy, encrypted, decrypt_cb));
210 } 239 }
211 240
212 void ProxyDecryptor::OnBufferDecrypted( 241 void ProxyDecryptor::OnBufferDecrypted(
213 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, 242 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
214 const scoped_refptr<DecoderBuffer>& encrypted, 243 const scoped_refptr<media::DecoderBuffer>& encrypted,
215 const Decryptor::DecryptCB& decrypt_cb, 244 const media::Decryptor::DecryptCB& decrypt_cb,
216 Decryptor::DecryptStatus status, 245 media::Decryptor::DecryptStatus status,
217 const scoped_refptr<DecoderBuffer>& decrypted) { 246 const scoped_refptr<media::DecoderBuffer>& decrypted) {
218 DVLOG(2) << "OnBufferDecrypted()"; 247 if (status == media::Decryptor::kSuccess ||
219 248 status == media::Decryptor::kError) {
220 if (status == Decryptor::kSuccess || status == Decryptor::kError) {
221 decrypt_cb.Run(status, decrypted); 249 decrypt_cb.Run(status, decrypted);
222 return; 250 return;
223 } 251 }
224 252
225 DCHECK_EQ(status, Decryptor::kNoKey); 253 DCHECK_EQ(status, media::Decryptor::kNoKey);
226 DVLOG(1) << "OnBufferDecrypted(): kNoKey fired"; 254 DVLOG(1) << "OnBufferDecrypted(): kNoKey fired";
227 { 255 {
228 base::AutoLock auto_lock(pending_decrypt_closures_lock_); 256 base::AutoLock auto_lock(lock_);
257 if (is_shutting_down_) {
258 DVLOG(1) << "OnBufferDecrypted(): fire decrypt callbacks with kError.";
259 decrypt_cb.Run(kError, NULL);
260 return;
261 }
229 pending_decrypt_closures_.push_back(base::Bind( 262 pending_decrypt_closures_.push_back(base::Bind(
230 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this), 263 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
231 message_loop_proxy, encrypted, decrypt_cb)); 264 message_loop_proxy, encrypted, decrypt_cb));
232 } 265 }
233 // TODO(xhwang): The same NeedKey may be fired multiple times here and also 266 // 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 267 // in Decrypt(). While the spec says only one NeedKey should be fired. Leave
235 // them as is since the spec about this may change. 268 // them as is since the spec about this may change.
236 FireNeedKey(client_, encrypted); 269 FireNeedKey(client_, encrypted);
237 } 270 }
238 271
239 } // namespace webkit_media 272 } // namespace webkit_media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698