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

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

Issue 10545036: Add PPAPI decryptor interfaces. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix PP_Resource/HostResource usage (hopefully), and update comments. 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <cassert>
dmichael (off chromium) 2012/08/08 22:24:02 I don't think you're using this?
Tom Finegan 2012/08/09 22:45:17 Removed.
6 #include <string>
7
8 #include "base/basictypes.h"
9 #include "base/string_number_conversions.h"
10 #include "base/memory/scoped_ptr.h"
dmichael (off chromium) 2012/08/08 22:24:02 you aren't using this. I'd suggest trying to not u
Tom Finegan 2012/08/09 22:45:17 Done.
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/cpp/completion_callback.h"
13 #include "ppapi/cpp/core.h"
14 #include "ppapi/cpp/instance.h"
15 #include "ppapi/cpp/module.h"
16 #include "ppapi/cpp/pass_ref.h"
17 #include "ppapi/cpp/resource.h"
18 #include "ppapi/cpp/var.h"
19 #include "ppapi/cpp/var_array_buffer.h"
20 #include "ppapi/cpp/dev/buffer_dev.h"
21 #include "ppapi/cpp/dev/content_decryptor_dev.h"
22 #include "ppapi/utility/completion_callback_factory.h"
23
24 namespace {
25
26 struct DecryptorMessage {
27 DecryptorMessage() : media_error(0), system_error(0) {}
28 std::string key_system;
29 std::string session_id;
30 std::string default_url;
31 std::string message_data;
32 uint16 media_error;
33 uint16 system_error;
34 };
35
36 struct DecryptedBlock {
37 DecryptedBlock() : request_id(0) {}
38 uint64_t request_id;
39 std::string data;
40 };
41
42 void CallOnMain(pp::CompletionCallback cb) {
43 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
44 }
45
46 } // namespace
47
48
49 // A wrapper class responsible for managing interaction between the browser and
50 // a Content Decryption Module (CDM).
51 class CDMWrapper : public pp::Instance,
52 public pp::ContentDecryptor_Dev {
53 public:
54 CDMWrapper(PP_Instance instance, pp::Module* module);
55 virtual ~CDMWrapper() {}
56
57 // PPP_ContentDecryptor_Dev methods
58 virtual bool GenerateKeyRequest(PP_Var key_system, PP_Var init_data) OVERRIDE;
59 virtual bool AddKey(PP_Var session_id, PP_Var key) OVERRIDE;
60 virtual bool CancelKeyRequest(PP_Var session_id) OVERRIDE;
61 virtual bool Decrypt(PP_Resource encrypted_block,
62 uint64_t request_id) OVERRIDE;
63
64 virtual bool DecryptAndDecode(PP_Resource encrypted_block,
65 uint64_t request_id) OVERRIDE {
66 return false;
67 }
68
69 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
70 return true;
71 }
72
73 private:
74 PP_Resource StringToBufferResource(const std::string& str);
75
76 // <code>PPB_ContentDecryptor_Dev</code> dispatchers. These are passed to
77 // <code>callback_factory_</code> to ensure that calls into
78 // <code>PPP_ContentDecryptor_Dev</code> are asynchronous.
79 void NeedKey(int32 result, const DecryptorMessage& decryptor_message);
80 void KeyAdded(int32 result, const DecryptorMessage& decryptor_message);
81 void KeyMessage(int32 result, const DecryptorMessage& decryptor_message);
82 void KeyError(int32 result, const DecryptorMessage& decryptor_message);
83 void DeliverBlock(int32 result, const DecryptedBlock& decrypted_block);
84
85 pp::CompletionCallbackFactory<CDMWrapper> callback_factory_;
86
87 virtual bool IsValidSessionId(std::string session_id) {
88 // TODO(tomfinegan): The CDM MUST handle multiple session IDs. This simple
89 // implementation exists for testing purposes.
90 return (!session_id_.empty() && session_id == session_id_);
91 }
92
93 // TODO(tomfinegan): This needs to be mappable to init data (key IDs in the
94 // WebM case). For WebM it most likely will be 1 key ID and 1 session per
95 // stream. For now we'll just use a random number.
96 uint32 next_session_id_;
dmichael (off chromium) 2012/08/08 22:24:02 I would suggest using ppapi/c/pp_stdint.h and uint
Tom Finegan 2012/08/09 22:45:17 Done.
97 std::string session_id_;
98
99 // Key ID obtained from init data passed to <code>GenerateKeyRequest</code>.
100 // As-is: WebM video specific; Inadequate for WebM with encrypted audio (A/V
101 // will not have same key ID/key/session ID). Probably inadequate for ISO.
102 std::string key_id_;
103
104 // TODO(tomfinegan): Should these be multimaps of session_id:key_system and
105 // session_id:key? Or am I completely confused? :)
dmichael (off chromium) 2012/08/08 22:24:02 Or map to some delegate class that is set up to ha
106 std::string key_;
107 std::string key_system_;
108 };
109
110 CDMWrapper::CDMWrapper(PP_Instance instance,
111 pp::Module* module)
112 : pp::Instance(instance),
113 pp::ContentDecryptor_Dev(this),
114 next_session_id_(0) {
115 callback_factory_.Initialize(this);
116 }
117
118 bool CDMWrapper::GenerateKeyRequest(PP_Var key_system_arg,
119 PP_Var init_data_arg) {
120
121 pp::Var init_data(pp::PASS_REF, init_data_arg);
122
123 // TODO(tomfinegan): Testing only implementation; init data will not always
124 // be the key ID.
125 pp::Var key_system_var(pp::PASS_REF, key_system_arg);
126
127 // TODO(tomfinegan): confirm support for the key system.
128
129 DecryptorMessage decryptor_message;
130 key_system_ = key_system_var.AsString();
131 decryptor_message.key_system = key_system_;
132 session_id_ = base::UintToString(next_session_id_++);
dmichael (off chromium) 2012/08/08 22:24:02 I think it would be better to use a stringstream i
Tom Finegan 2012/08/09 22:45:17 Done.
133 decryptor_message.session_id = session_id_;
134 decryptor_message.default_url = "http://www.google.com";
135 decryptor_message.message_data = "key request";
136
137 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::KeyMessage,
dmichael (off chromium) 2012/08/08 22:24:02 I don't know whether you want to rely on this...
138 decryptor_message));
139 return true;
140 }
141
142 bool CDMWrapper::AddKey(PP_Var session_id_var, PP_Var key_arg) {
143 pp::Var session_id(pp::PASS_REF, session_id_var);
144 if (!IsValidSessionId(session_id.AsString()))
145 return false;
146
147 pp::VarArrayBuffer key(pp::Var(pp::PASS_REF, key_arg));
148 if (!key.is_array_buffer())
dmichael (off chromium) 2012/08/08 22:24:02 you should always check is_array_buffer _before_ u
Tom Finegan 2012/08/09 22:45:17 Done/checked in c++ wrapper.
149 return false;
150
151 key_.assign(reinterpret_cast<char*>(key.Map()), key.ByteLength());
152
153 DecryptorMessage decryptor_message;
154 decryptor_message.key_system = key_system_;
155 decryptor_message.session_id = session_id_;
156 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::KeyAdded,
157 decryptor_message));
158 return true;
159 }
160
161 bool CDMWrapper::CancelKeyRequest(PP_Var session_id_arg) {
162 pp::Var session_id_var(pp::PASS_REF, session_id_arg);
163
164 if (!IsValidSessionId(session_id_var.AsString()))
165 return false;
166
167 // TODO(tomfinegan): cancel pending key request in CDM.
168
169 return true;
170 }
171
172 bool CDMWrapper::Decrypt(PP_Resource encrypted_block,
173 uint64_t request_id) {
174 pp::Buffer_Dev block_buffer(encrypted_block);
175 if (!block_buffer.data()) {
176 return false;
177 }
178
179 DecryptedBlock decrypted_block;
180 decrypted_block.request_id = request_id;
181 decrypted_block.data = "Pretend I'm decrypted data!";
182 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::DeliverBlock,
183 decrypted_block));
184 return true;
185 }
186
187 PP_Resource CDMWrapper::StringToBufferResource(const std::string& str) {
dmichael (off chromium) 2012/08/08 22:24:02 I don't think a string is the best way to represen
Tom Finegan 2012/08/09 22:45:17 Discussed offline.
188 if (str.empty())
189 return 0;
190
191 pp::Buffer_Dev buffer(this, str.size());
192 if (!buffer.data())
193 return 0;
194
195 memcpy(buffer.data(), str.data(), str.size());
196 return buffer.detach();
197 }
198
199 void CDMWrapper::NeedKey(int32 result,
200 const DecryptorMessage& decryptor_message) {
201 pp::Var key_system(decryptor_message.key_system);
202 pp::Var session_id(decryptor_message.session_id);
203 pp::Var init_data(decryptor_message.message_data);
204 pp::ContentDecryptor_Dev::NeedKey(key_system.pp_var(),
205 session_id.pp_var(),
206 init_data.pp_var());
207 }
208
209 void CDMWrapper::KeyAdded(int32 result,
210 const DecryptorMessage& decryptor_message) {
211 PP_Var key_system = pp::Var(decryptor_message.key_system).pp_var();
212 PP_Var session_id = pp::Var(decryptor_message.session_id).pp_var();
213 pp::ContentDecryptor_Dev::KeyAdded(key_system, session_id);
214 }
215
216 void CDMWrapper::KeyMessage(int32 result,
217 const DecryptorMessage& decryptor_message) {
218 PP_Var key_system = pp::Var(decryptor_message.key_system).pp_var();
219 PP_Var session_id = pp::Var(decryptor_message.session_id).pp_var();
220 PP_Resource message =
221 StringToBufferResource(decryptor_message.message_data);
222 PP_Var default_url = pp::Var(decryptor_message.default_url).pp_var();
223 pp::ContentDecryptor_Dev::KeyMessage(key_system,
224 session_id,
225 message,
226 default_url);
227 }
228
229 void CDMWrapper::KeyError(int32 result,
230 const DecryptorMessage& decryptor_message) {
231 PP_Var key_system = pp::Var(decryptor_message.key_system).pp_var();
232 PP_Var session_id = pp::Var(decryptor_message.session_id).pp_var();
233 pp::ContentDecryptor_Dev::KeyError(key_system,
234 session_id,
235 decryptor_message.media_error,
236 decryptor_message.system_error);
237 }
238
239 void CDMWrapper::DeliverBlock(int32 result,
240 const DecryptedBlock& decrypted_block) {
241 PP_Resource decrypted_resource = StringToBufferResource(
242 decrypted_block.data);
243 if (decrypted_resource) {
244 pp::ContentDecryptor_Dev::DeliverBlock(decrypted_resource,
245 decrypted_block.request_id);
246 }
247 }
248
249 // This object is the global object representing this plugin library as long
250 // as it is loaded.
251 class MyModule : public pp::Module {
252 public:
253 MyModule() : pp::Module() {}
254 virtual ~MyModule() {}
255
256 virtual pp::Instance* CreateInstance(PP_Instance instance) {
257 return new CDMWrapper(instance, this);
258 }
259 };
260
261 namespace pp {
262
263 // Factory function for your specialization of the Module object.
264 Module* CreateModule() {
265 return new MyModule();
266 }
267
268 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698