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

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: Fix broken ChunkDemuxerTest due to null MessageLoop::Current() 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
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) {
51 } 69 }
52 70
53 ProxyDecryptor::~ProxyDecryptor() { 71 ProxyDecryptor::~ProxyDecryptor() {
54 } 72 }
55 73
56 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system, 74 void ProxyDecryptor::GenerateKeyRequest(const std::string& key_system,
57 const uint8* init_data, 75 const uint8* init_data,
58 int init_data_length) { 76 int init_data_length) {
59 // We do not support run-time switching of decryptors. GenerateKeyRequest() 77 // We do not support run-time switching of decryptors. GenerateKeyRequest()
60 // only creates a new decryptor when |decryptor_| is not initialized. 78 // only creates a new decryptor when |decryptor_| is not initialized.
79 DVLOG(1) << "GenerateKeyRequest: key_system = " << key_system;
61 if (!decryptor_.get()) { 80 if (!decryptor_.get()) {
62 base::AutoLock auto_lock(lock_); 81 base::AutoLock auto_lock(lock_);
63 decryptor_ = CreateDecryptor(key_system); 82 decryptor_ = CreateDecryptor(key_system);
64 } 83 }
65 84
66 DCHECK(client_);
67 if (!decryptor_.get()) { 85 if (!decryptor_.get()) {
68 client_->KeyError(key_system, "", media::Decryptor::kUnknownError, 0); 86 client_->KeyError(key_system, "", media::Decryptor::kUnknownError, 0);
69 return; 87 return;
70 } 88 }
71 89
72 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length); 90 decryptor_->GenerateKeyRequest(key_system, init_data, init_data_length);
73 } 91 }
74 92
75 void ProxyDecryptor::AddKey(const std::string& key_system, 93 void ProxyDecryptor::AddKey(const std::string& key_system,
76 const uint8* key, 94 const uint8* key,
77 int key_length, 95 int key_length,
78 const uint8* init_data, 96 const uint8* init_data,
79 int init_data_length, 97 int init_data_length,
80 const std::string& session_id) { 98 const std::string& session_id) {
99 DVLOG(1) << "AddKey()";
100
81 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. 101 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
82 DCHECK(decryptor_.get()); 102 DCHECK(decryptor_.get());
83 decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length, 103 decryptor_->AddKey(key_system, key, key_length, init_data, init_data_length,
84 session_id); 104 session_id);
105
106 std::vector<base::Closure> closures_to_run;
107 {
108 base::AutoLock auto_lock(lock_);
109 std::swap(pending_decrypt_closures_, closures_to_run);
110 }
111
112 // Fire all pending callbacks here because only the |decryptor_| knows if the
113 // pending buffers can be decrypted or not.
114 for (std::vector<base::Closure>::iterator iter = closures_to_run.begin();
115 iter != closures_to_run.end();
116 ++iter) {
117 iter->Run();
118 }
85 } 119 }
86 120
87 void ProxyDecryptor::CancelKeyRequest(const std::string& key_system, 121 void ProxyDecryptor::CancelKeyRequest(const std::string& key_system,
88 const std::string& session_id) { 122 const std::string& session_id) {
123 DVLOG(1) << "CancelKeyRequest()";
124
89 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. 125 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
90 DCHECK(decryptor_.get()); 126 DCHECK(decryptor_.get());
91 decryptor_->CancelKeyRequest(key_system, session_id); 127 decryptor_->CancelKeyRequest(key_system, session_id);
92 } 128 }
93 129
94 void ProxyDecryptor::Decrypt( 130 void ProxyDecryptor::Decrypt(
95 const scoped_refptr<media::DecoderBuffer>& encrypted, 131 const scoped_refptr<media::DecoderBuffer>& encrypted,
96 const DecryptCB& decrypt_cb) { 132 const DecryptCB& decrypt_cb) {
97 // This is safe as we do not replace/delete an existing decryptor at run-time. 133 // This is safe as we do not replace/delete an existing decryptor at run-time.
98 media::Decryptor* decryptor = NULL; 134 media::Decryptor* decryptor = NULL;
99 { 135 {
100 base::AutoLock auto_lock(lock_); 136 base::AutoLock auto_lock(lock_);
101 decryptor = decryptor_.get(); 137 decryptor = decryptor_.get();
102 } 138 if (!decryptor) {
103 if (!decryptor) { 139 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized.";
104 DVLOG(1) << "ProxyDecryptor::Decrypt(): decryptor not initialized."; 140 pending_decrypt_closures_.push_back(
105 decrypt_cb.Run(kError, NULL); 141 base::Bind(&ProxyDecryptor::DecryptOnMessageLoop,
106 return; 142 base::Unretained(this),
143 base::MessageLoopProxy::current(), encrypted,
144 decrypt_cb));
145 // TODO(xhwang): The same NeedKey may be fired here and multiple times in
146 // OnBufferDecrypted(). While the spec says only one NeedKey should be
147 // fired. Leave them as is since the spec about this may change.
148 FireNeedKey(client_, encrypted);
149 return;
150 }
107 } 151 }
108 152
109 decryptor->Decrypt(encrypted, decrypt_cb); 153 decryptor->Decrypt(encrypted, base::Bind(
154 &ProxyDecryptor::OnBufferDecrypted, base::Unretained(this),
155 base::MessageLoopProxy::current(), encrypted, decrypt_cb));
110 } 156 }
111 157
112 scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor( 158 scoped_ptr<media::Decryptor> ProxyDecryptor::CreatePpapiDecryptor(
113 const std::string& key_system) { 159 const std::string& key_system) {
114 DCHECK(client_); 160 DCHECK(client_);
115 DCHECK(web_media_player_client_); 161 DCHECK(web_media_player_client_);
116 DCHECK(web_frame_); 162 DCHECK(web_frame_);
117 163
118 std::string plugin_type = GetPluginType(key_system); 164 std::string plugin_type = GetPluginType(key_system);
119 DCHECK(!plugin_type.empty()); 165 DCHECK(!plugin_type.empty());
(...skipping 14 matching lines...) Expand all
134 180
135 if (CanUseAesDecryptor(key_system)) 181 if (CanUseAesDecryptor(key_system))
136 return scoped_ptr<media::Decryptor>(new media::AesDecryptor(client_)); 182 return scoped_ptr<media::Decryptor>(new media::AesDecryptor(client_));
137 183
138 // We only support AesDecryptor and PpapiDecryptor. So if we cannot 184 // We only support AesDecryptor and PpapiDecryptor. So if we cannot
139 // use the AesDecryptor, then we'll try to create a PpapiDecryptor for given 185 // use the AesDecryptor, then we'll try to create a PpapiDecryptor for given
140 // |key_system|. 186 // |key_system|.
141 return CreatePpapiDecryptor(key_system); 187 return CreatePpapiDecryptor(key_system);
142 } 188 }
143 189
190 void ProxyDecryptor::DecryptOnMessageLoop(
191 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
192 const scoped_refptr<media::DecoderBuffer>& encrypted,
193 const media::Decryptor::DecryptCB& decrypt_cb) {
194 DCHECK(decryptor_.get());
195
196 if (!message_loop_proxy->BelongsToCurrentThread()) {
197 message_loop_proxy->PostTask(FROM_HERE, base::Bind(
198 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
199 message_loop_proxy, encrypted, decrypt_cb));
200 return;
201 }
202
203 decryptor_->Decrypt(encrypted, base::Bind(&ProxyDecryptor::OnBufferDecrypted,
204 base::Unretained(this), message_loop_proxy, encrypted, decrypt_cb));
205 }
206
207 void ProxyDecryptor::OnBufferDecrypted(
208 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
209 const scoped_refptr<media::DecoderBuffer>& encrypted,
210 const media::Decryptor::DecryptCB& decrypt_cb,
211 media::Decryptor::DecryptStatus status,
212 const scoped_refptr<media::DecoderBuffer>& decrypted) {
213 if (status == media::Decryptor::kSuccess ||
214 status == media::Decryptor::kError) {
215 decrypt_cb.Run(status, decrypted);
216 return;
217 }
218
219 DCHECK_EQ(status, media::Decryptor::kNoKey);
220 DVLOG(1) << "OnBufferDecrypted(): kNoKey fired";
221 {
222 base::AutoLock auto_lock(lock_);
223 pending_decrypt_closures_.push_back(base::Bind(
224 &ProxyDecryptor::DecryptOnMessageLoop, base::Unretained(this),
225 message_loop_proxy, encrypted, decrypt_cb));
226 }
227 // TODO(xhwang): The same NeedKey may be fired multiple times here and also
228 // in Decrypt(). While the spec says only one NeedKey should be fired. Leave
229 // them as is since the spec about this may change.
230 FireNeedKey(client_, encrypted);
231 }
232
144 } // namespace webkit_media 233 } // namespace webkit_media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698