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

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
« no previous file with comments | « webkit/media/crypto/proxy_decryptor.h ('k') | webkit/media/crypto/proxy_decryptor_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
9 #include "base/bind.h"
10 #include "base/location.h"
7 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop_proxy.h"
8 #include "media/base/decoder_buffer.h" 13 #include "media/base/decoder_buffer.h"
9 #include "media/base/decryptor_client.h" 14 #include "media/base/decryptor_client.h"
10 #include "media/crypto/aes_decryptor.h" 15 #include "media/crypto/aes_decryptor.h"
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" 17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
13 #include "webkit/media/crypto/key_systems.h" 18 #include "webkit/media/crypto/key_systems.h"
14 #include "webkit/media/crypto/ppapi_decryptor.h" 19 #include "webkit/media/crypto/ppapi_decryptor.h"
15 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 20 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
16 #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h" 21 #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
17 // 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
(...skipping 16 matching lines...) Expand all
34 if (!web_plugin) 39 if (!web_plugin)
35 return NULL; 40 return NULL;
36 41
37 DCHECK(!web_plugin->isPlaceholder()); // Prevented by WebKit. 42 DCHECK(!web_plugin->isPlaceholder()); // Prevented by WebKit.
38 // 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.
39 webkit::ppapi::WebPluginImpl* ppapi_plugin = 44 webkit::ppapi::WebPluginImpl* ppapi_plugin =
40 static_cast<webkit::ppapi::WebPluginImpl*>(web_plugin); 45 static_cast<webkit::ppapi::WebPluginImpl*>(web_plugin);
41 return ppapi_plugin->instance(); 46 return ppapi_plugin->instance();
42 } 47 }
43 48
49 // TODO(xhwang): Simplify this function. This is mostly caused by the fact that
50 // we need to copy a scoped_array<uint8>.
51 static void FireNeedKey(media::DecryptorClient* client,
52 const scoped_refptr<media::DecoderBuffer>& encrypted) {
53 DCHECK(client);
54 DCHECK(encrypted);
55 DCHECK(encrypted->GetDecryptConfig());
56 std::string key_id = encrypted->GetDecryptConfig()->key_id();
57 scoped_array<uint8> key_id_array(new uint8[key_id.size()]);
58 memcpy(key_id_array.get(), key_id.data(), key_id.size());
59 client->NeedKey("", "", key_id_array.Pass(), key_id.size());
60 }
61
44 ProxyDecryptor::ProxyDecryptor( 62 ProxyDecryptor::ProxyDecryptor(
45 media::DecryptorClient* decryptor_client, 63 media::DecryptorClient* decryptor_client,
46 WebKit::WebMediaPlayerClient* web_media_player_client, 64 WebKit::WebMediaPlayerClient* web_media_player_client,
47 WebKit::WebFrame* web_frame) 65 WebKit::WebFrame* web_frame)
48 : client_(decryptor_client), 66 : client_(decryptor_client),
49 web_media_player_client_(web_media_player_client), 67 web_media_player_client_(web_media_player_client),
50 web_frame_(web_frame) { 68 web_frame_(web_frame),
69 stopped_(false) {
51 } 70 }
52 71
53 ProxyDecryptor::~ProxyDecryptor() { 72 ProxyDecryptor::~ProxyDecryptor() {
54 } 73 }
55 74
56 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system, 75 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system,
57 const uint8* init_data, 76 const uint8* init_data,
58 int init_data_length) { 77 int init_data_length) {
59 // We do not support run-time switching of decryptors. GenerateKeyRequest() 78 // We do not support run-time switching of decryptors. GenerateKeyRequest()
60 // only creates a new decryptor when |decryptor_| is not initialized. 79 // only creates a new decryptor when |decryptor_| is not initialized.
80 DVLOG(1) << "GenerateKeyRequest: key_system = " << key_system;
61 if (!decryptor_.get()) { 81 if (!decryptor_.get()) {
62 base::AutoLock auto_lock(lock_); 82 base::AutoLock auto_lock(lock_);
63 decryptor_ = CreateDecryptor(key_system); 83 decryptor_ = CreateDecryptor(key_system);
64 } 84 }
65 85
66 DCHECK(client_);
67 if (!decryptor_.get()) { 86 if (!decryptor_.get()) {
68 client_->KeyError(key_system, "", media::Decryptor::kUnknownError, 0); 87 client_->KeyError(key_system, "", media::Decryptor::kUnknownError, 0);
69 return; 88 return;
70 } 89 }
71 90
72 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length); 91 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length);
73 } 92 }
74 93
75 void ProxyDecryptor::AddKey(const std::string& key_system, 94 void ProxyDecryptor::AddKey(const std::string& key_system,
76 const uint8* key, 95 const uint8* key,
77 int key_length, 96 int key_length,
78 const uint8* init_data, 97 const uint8* init_data,
79 int init_data_length, 98 int init_data_length,
80 const std::string& session_id) { 99 const std::string& session_id) {
100 DVLOG(1) << "AddKey()";
101
81 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. 102 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
82 DCHECK(decryptor_.get()); 103 DCHECK(decryptor_.get());
83 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,
84 session_id); 105 session_id);
106
107 std::vector<base::Closure> closures_to_run;
108 {
109 base::AutoLock auto_lock(lock_);
110 std::swap(pending_decrypt_closures_, closures_to_run);
111 }
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();
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<media::DecoderBuffer>& encrypted,
96 const DecryptCB& decrypt_cb) { 133 const DecryptCB& decrypt_cb) {
97 // 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.
98 media::Decryptor* decryptor = NULL; 135 media::Decryptor* decryptor = NULL;
99 { 136 {
100 base::AutoLock auto_lock(lock_); 137 base::AutoLock auto_lock(lock_);
138 if (stopped_) {
139 DVLOG(1) << "Decrypt(): fire decrypt callbacks with kError.";
140 decrypt_cb.Run(kError, NULL);
141 return;
142 }
101 decryptor = decryptor_.get(); 143 decryptor = decryptor_.get();
102 } 144 if (!decryptor) {
103 if (!decryptor) { 145 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized.";
104 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized."; 146 pending_decrypt_closures_.push_back(
105 decrypt_cb.Run(kError, NULL); 147 base::Bind(&ProxyDecryptor::DecryptOnMessageLoop,
106 return; 148 base::Unretained(this),
149 base::MessageLoopProxy::current(), encrypted,
150 decrypt_cb));
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 }
107 } 157 }
108 158
109 decryptor->Decrypt(encrypted, decrypt_cb); 159 decryptor->Decrypt(encrypted, base::Bind(
160 &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this),
161 base::MessageLoopProxy::current(), encrypted, decrypt_cb));
162 }
163
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 stopped_ = 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 }
110 } 181 }
111 182
112 scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor( 183 scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor(
113 const std::string& key_system) { 184 const std::string& key_system) {
114 DCHECK(client_); 185 DCHECK(client_);
115 DCHECK(web_media_player_client_); 186 DCHECK(web_media_player_client_);
116 DCHECK(web_frame_); 187 DCHECK(web_frame_);
117 188
118 std::string plugin_type = GetPluginType(key_system); 189 std::string plugin_type = GetPluginType(key_system);
119 DCHECK(!plugin_type.empty()); 190 DCHECK(!plugin_type.empty());
(...skipping 14 matching lines...) Expand all
134 205
135 if (CanUseAesDecryptor(key_system)) 206 if (CanUseAesDecryptor(key_system))
136 return scoped_ptr<media::Decryptor>(new media::AesDecryptor(client_)); 207 return scoped_ptr<media::Decryptor>(new media::AesDecryptor(client_));
137 208
138 // We only support AesDecryptor and PpapiDecryptor. So if we cannot 209 // We only support AesDecryptor and PpapiDecryptor. So if we cannot
139 // 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
140 // |key_system|. 211 // |key_system|.
141 return CreatePpapiDecryptor(key_system); 212 return CreatePpapiDecryptor(key_system);
142 } 213 }
143 214
215 void ProxyDecryptor::DecryptOnMessageLoop(
216 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
217 const scoped_refptr<media::DecoderBuffer>& encrypted,
218 const media::Decryptor::DecryptCB& decrypt_cb) {
219 DCHECK(decryptor_.get());
220
221 if (!message_loop_proxy->BelongsToCurrentThread()) {
222 message_loop_proxy->PostTask(FROM_HERE, base::Bind(
223 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
224 message_loop_proxy, encrypted, decrypt_cb));
225 return;
226 }
227
228 {
229 base::AutoLock auto_lock(lock_);
230 if (stopped_) {
231 DVLOG(1) << "DecryptOnMessageLoop(): fire decrypt callbacks with kError.";
232 decrypt_cb.Run(kError, NULL);
233 return;
234 }
235 }
236
237 decryptor_->Decrypt(encrypted, base::Bind(
238 &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this),
239 message_loop_proxy, encrypted, decrypt_cb));
240 }
241
242 void ProxyDecryptor::OnBufferDecrypted(
243 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
244 const scoped_refptr<media::DecoderBuffer>& encrypted,
245 const media::Decryptor::DecryptCB& decrypt_cb,
246 media::Decryptor::DecryptStatus status,
247 const scoped_refptr<media::DecoderBuffer>& decrypted) {
248 if (status == media::Decryptor::kSuccess ||
249 status == media::Decryptor::kError) {
250 decrypt_cb.Run(status, decrypted);
251 return;
252 }
253
254 DCHECK_EQ(status, media::Decryptor::kNoKey);
255 DVLOG(1) << "OnBufferDecrypted(): kNoKey fired";
256 {
257 base::AutoLock auto_lock(lock_);
258 if (stopped_) {
259 DVLOG(1) << "OnBufferDecrypted(): fire decrypt callbacks with kError.";
260 decrypt_cb.Run(kError, NULL);
261 return;
262 }
263 pending_decrypt_closures_.push_back(base::Bind(
264 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
265 message_loop_proxy, encrypted, decrypt_cb));
266 }
267 // TODO(xhwang): The same NeedKey may be fired multiple times here and also
268 // in Decrypt(). While the spec says only one NeedKey should be fired. Leave
269 // them as is since the spec about this may change.
270 FireNeedKey(client_, encrypted);
271 }
272
144 } // namespace webkit_media 273 } // namespace webkit_media
OLDNEW
« no previous file with comments | « webkit/media/crypto/proxy_decryptor.h ('k') | webkit/media/crypto/proxy_decryptor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698