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

Side by Side Diff: ppapi/examples/content_decryptor/content_decryptor.cc

Issue 10545036: Add PPAPI decryptor interfaces. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sorry for the rebase noise-- unavoidable due to move from work to home PC. 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>
6 #include <string>
7
8 #include "base/basictypes.h"
9 #include "base/rand_util.h"
10 #include "base/values.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/cpp/completion_callback.h"
14 #include "ppapi/cpp/core.h"
15 #include "ppapi/cpp/instance.h"
16 #include "ppapi/cpp/module.h"
17 #include "ppapi/cpp/resource.h"
18 #include "ppapi/cpp/var.h"
19 #include "ppapi/cpp/dev/buffer_dev.h"
20 #include "ppapi/cpp/dev/content_decryptor_dev.h"
21 #include "ppapi/shared_impl/var.h"
22 #include "ppapi/utility/completion_callback_factory.h"
23
24 using ppapi::StringVar;
25
26 namespace {
27
28 struct DecryptorMessage {
29 DecryptorMessage() : media_error(0), system_error(0) {}
30 std::string key_system;
31 std::string session_id;
32 std::string default_url;
33 std::string message_data;
34 uint16 media_error;
35 uint16 system_error;
36 };
37
38 struct DecryptedData {
ddorwin 2012/07/28 01:43:26 This will be different for each type of data retur
Tom Finegan 2012/07/31 15:34:26 Renamed to DecryptedBlock.
39 DecryptedData() : callback(PP_MakeCompletionCallback(NULL, NULL)) {}
40 PP_CompletionCallback callback;
41 std::string data;
42 };
43
44 bool IsMainThread() {
45 return pp::Module::Get()->core()->IsMainThread();
46 }
47
48 void CallOnMain(pp::CompletionCallback cb) {
49 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
50 }
51
52 } // namespace
53
54
55 // A wrapper class responsible for managing interaction between the browser and
56 // a Content Decryption Module (CDM).
57 class CDMWrapper : public pp::Instance,
58 public pp::ContentDecryptor_Dev {
59 public:
60 const static size_t kSessionIdLength = 8;
ddorwin 2012/07/28 01:43:26 Bits? Bytes? 8 seems odd for either. I would just
Tom Finegan 2012/07/31 15:34:26 Just pulled a number out of the air-- removed, doi
61 CDMWrapper(PP_Instance instance, pp::Module* module);
62 virtual ~CDMWrapper() {}
63
64 // PPP_ContentDecryptor_Dev methods
65 virtual bool GenerateKeyRequest(PP_Var key_system, PP_Resource init_data);
66 virtual bool AddKey(PP_Var session_id, PP_Resource key);
67 virtual bool CancelKeyRequest(PP_Var session_id);
68 virtual bool Decrypt(PP_Resource encrypted_block,
69 PP_CompletionCallback callback);
70
71 virtual bool DecryptAndDecode(PP_Resource encrypted_block,
72 PP_CompletionCallback callback) {
73 return false;
74 }
75
76 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
77 return true;
78 }
79
80 private:
81 PP_Resource StringToBufferResource(const std::string& str);
82
83 // <code>PPB_ContentDecryptor_Dev</code> dispatchers. These are passed to
84 // <code>callback_factory_</code> to ensure that calls into
85 // <code>PPP_ContentDecryptor_Dev</code> are asynchronous.
86 void NeedKey(int32 result, const DecryptorMessage& decryptor_message);
87 void KeyAdded(int32 result, const DecryptorMessage& decryptor_message);
88 void KeyMessage(int32 result, const DecryptorMessage& decryptor_message);
89 void KeyError(int32 result, const DecryptorMessage& decryptor_message);
90 void DeliverBlock(int32 result, const DecryptedData& decrypted_data);
91
92 pp::CompletionCallbackFactory<CDMWrapper> callback_factory_;
93
94 virtual bool IsValidSessionId(std::string session_id) {
95 // TODO(tomfinegan): The CDM MUST handle multiple session IDs. This simple
96 // implementation exists for testing purposes.
97 return (!session_id_.empty() && session_id == session_id_);
98 }
99
100 // TODO(tomfinegan): This needs to be mappable to init data (key IDs in the
101 // WebM case). For WebM it most likely will be 1 key ID and 1 session per
102 // stream. For now we'll just use a random number.
103 std::string session_id_;
104
105 // Key ID obtained from init data passed to <code>GenerateKeyRequest</code>.
106 // As-is: WebM video specific; Inadequate for WebM with encrypted audio (A/V
107 // will not have same key ID/key/session ID). Probably inadequate for ISO.
108 std::string key_id_;
109
110 // TODO(tomfinegan): Should these be multimaps of session_id:key_system and
111 // session_id:key? Or am I completely confused? :)
112 std::string key_;
113 std::string key_system_;
114 };
115
116 CDMWrapper::CDMWrapper(PP_Instance instance,
117 pp::Module* module)
118 : pp::Instance(instance),
119 pp::ContentDecryptor_Dev(this) {
120 callback_factory_.Initialize(this);
121 }
122
123 bool CDMWrapper::GenerateKeyRequest(PP_Var key_system_arg,
124 PP_Resource init_data) {
125 if (init_data) {
126 pp::Buffer_Dev init_buffer(init_data);
127 if (!init_buffer.data() || init_buffer.size() == 0) {
128 return false;
129 }
130
131 // TODO(tomfinegan): Testing only implementation; init data will not always
132 // be the key ID.
133 key_id_.assign(reinterpret_cast<char*>(init_buffer.data()),
134 init_buffer.size());
135 }
136
137 StringVar* key_system_var = StringVar::FromPPVar(key_system_arg);
138
139 // TODO(tomfinegan): confirm support for the key system.
140
141 DecryptorMessage decryptor_message;
142 key_system_ = key_system_var->value();
143 decryptor_message.key_system = key_system_;
144 session_id_ = base::RandBytesAsString(kSessionIdLength);
ddorwin 2012/07/28 01:43:26 For Clear Key, I think we should just use an incre
Tom Finegan 2012/07/31 15:34:26 Done.
145 decryptor_message.session_id = session_id_;
146 decryptor_message.default_url = "http://www.google.com";
147 decryptor_message.message_data = "key request";
148
149 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::KeyMessage,
150 decryptor_message));
151 return true;
152 }
153
154 bool CDMWrapper::AddKey(PP_Var session_id_var, PP_Resource key) {
155 if (!IsValidSessionId(StringVar::FromPPVar(session_id_var)->value()))
156 return false;
157
158 pp::Buffer_Dev key_buffer(key);
159 if (!key_buffer.data())
160 return false;
161
162 key_.assign(reinterpret_cast<char*>(key_buffer.data()), key_buffer.size());
163
164 DecryptorMessage decryptor_message;
165 decryptor_message.key_system = key_system_;
166 decryptor_message.session_id = session_id_;
167 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::KeyAdded,
168 decryptor_message));
169 return true;
170 }
171
172 bool CDMWrapper::CancelKeyRequest(PP_Var session_id_var) {
173 std::string session_id = StringVar::FromPPVar(session_id_var)->value();
174
175 // TODO(tomfinegan): cancel pending key request in CDM.
176
177 return true;
178 }
179
180 bool CDMWrapper::Decrypt(PP_Resource encrypted_block,
181 PP_CompletionCallback callback) {
182 pp::Buffer_Dev block_buffer(encrypted_block);
183 if (!block_buffer.data() || !callback.func) {
184 return false;
185 }
186
187 DecryptedData decrypted_data;
188 decrypted_data.callback = callback;
189 decrypted_data.data = "Pretend I'm decrypted data!";
190 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::DeliverBlock,
191 decrypted_data));
ddorwin 2012/07/28 01:43:26 This is probably a copy, which means we're copying
192 return true;
193 }
194
195 PP_Resource CDMWrapper::StringToBufferResource(const std::string& str) {
196 if (str.empty())
197 return 0;
198
199 pp::Buffer_Dev buffer(this, str.size());
200 if (!buffer.data())
201 return 0;
202
203 memcpy(buffer.data(), str.data(), str.size());
204 return buffer.detach();
205 }
206
207 void CDMWrapper::NeedKey(int32 result,
208 const DecryptorMessage& decryptor_message) {
209 PP_Var key_system = StringVar::StringToPPVar(decryptor_message.key_system);
210 PP_Var session_id = StringVar::StringToPPVar(decryptor_message.session_id);
211 PP_Resource init_data =
212 StringToBufferResource(decryptor_message.message_data);
213 pp::ContentDecryptor_Dev::NeedKey(key_system, session_id, init_data);
214 }
215
216 void CDMWrapper::KeyAdded(int32 result,
217 const DecryptorMessage& decryptor_message) {
218 PP_Var key_system = StringVar::StringToPPVar(decryptor_message.key_system);
219 PP_Var session_id = StringVar::StringToPPVar(decryptor_message.session_id);
220 pp::ContentDecryptor_Dev::KeyAdded(key_system, session_id);
221 }
222
223 void CDMWrapper::KeyMessage(int32 result,
224 const DecryptorMessage& decryptor_message) {
225 PP_Var key_system = StringVar::StringToPPVar(decryptor_message.key_system);
226 PP_Var session_id = StringVar::StringToPPVar(decryptor_message.session_id);
227 PP_Resource message =
228 StringToBufferResource(decryptor_message.message_data);
229 PP_Var default_url =
230 StringVar::StringToPPVar(decryptor_message.default_url);
231 pp::ContentDecryptor_Dev::KeyMessage(key_system,
232 session_id,
233 message,
234 default_url);
235 }
236
237 void CDMWrapper::KeyError(int32 result,
238 const DecryptorMessage& decryptor_message) {
239 PP_Var key_system = StringVar::StringToPPVar(decryptor_message.key_system);
240 PP_Var session_id = StringVar::StringToPPVar(decryptor_message.session_id);
241 pp::ContentDecryptor_Dev::KeyError(key_system,
242 session_id,
243 decryptor_message.media_error,
244 decryptor_message.system_error);
245 }
246
247 void CDMWrapper::DeliverBlock(int32 result,
248 const DecryptedData& decrypted_data) {
249 PP_Resource decrypted_resource = StringToBufferResource(
250 decrypted_data.data);
251 if (decrypted_resource) {
252 pp::ContentDecryptor_Dev::DeliverBlock(decrypted_resource,
253 decrypted_data.callback);
254 }
255 }
256
257 // This object is the global object representing this plugin library as long
258 // as it is loaded.
259 class MyModule : public pp::Module {
260 public:
261 MyModule() : pp::Module() {}
262 virtual ~MyModule() {}
263
264 virtual pp::Instance* CreateInstance(PP_Instance instance) {
265 return new CDMWrapper(instance, this);
266 }
267 };
268
269 namespace pp {
270
271 // Factory function for your specialization of the Module object.
272 Module* CreateModule() {
273 return new MyModule();
274 }
275
276 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698