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

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

Issue 10827280: Add PPAPI decryptor implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix proxied interface definition. 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 <cstring> // std::memcpy
6 #include <sstream> // std::ostringstream
7
8 #include "base/compiler_specific.h" // for OVERRIDE.
9 #include "ppapi/c/pp_errors.h"
10 #include "ppapi/c/pp_stdint.h"
11 #include "ppapi/cpp/completion_callback.h"
12 #include "ppapi/cpp/core.h"
13 #include "ppapi/cpp/instance.h"
14 #include "ppapi/cpp/module.h"
15 #include "ppapi/cpp/pass_ref.h"
16 #include "ppapi/cpp/resource.h"
17 #include "ppapi/cpp/var.h"
18 #include "ppapi/cpp/var_array_buffer.h"
19 #include "ppapi/cpp/dev/buffer_dev.h"
20 #include "ppapi/cpp/private/content_decryptor_private.h"
21 #include "ppapi/utility/completion_callback_factory.h"
22
23 namespace {
24
25 struct DecryptorMessage {
26 DecryptorMessage() : media_error(0), system_code(0) {}
27 std::string key_system;
28 std::string session_id;
29 std::string default_url;
30 std::string message_data;
31 int32_t media_error;
32 int32_t system_code;
33 };
34
35 struct DecryptedBlock {
36 DecryptedBlock() : request_id(0) {}
37 int32_t request_id;
38 std::string data;
39 };
40
41 void CallOnMain(pp::CompletionCallback cb) {
42 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
43 }
44
45 } // namespace
46
47
48 // A wrapper class responsible for managing interaction between the browser and
49 // a Content Decryption Module (CDM).
50 class CDMWrapper : public pp::Instance,
51 public pp::ContentDecryptor_Private {
52 public:
53 CDMWrapper(PP_Instance instance, pp::Module* module);
54 virtual ~CDMWrapper() {}
55
56 // PPP_ContentDecryptor_Private methods
57 virtual bool GenerateKeyRequest(const std::string& key_system,
58 pp::VarArrayBuffer init_data) OVERRIDE;
59 virtual bool AddKey(const std::string& session_id,
60 pp::VarArrayBuffer key) OVERRIDE;
61 virtual bool CancelKeyRequest(const std::string& session_id) OVERRIDE;
62 virtual bool Decrypt(pp::Buffer_Dev encrypted_block,
63 int32_t request_id) OVERRIDE;
64
65 virtual bool DecryptAndDecode(pp::Buffer_Dev encrypted_block,
66 int32_t request_id) OVERRIDE {
67 return false;
68 }
69
70 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
71 return true;
72 }
73
74 private:
75 PP_Resource StringToBufferResource(const std::string& str);
76
77 // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
78 // <code>callback_factory_</code> to ensure that calls into
79 // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
80 void NeedKey(int32_t result, const DecryptorMessage& decryptor_message);
81 void KeyAdded(int32_t result, const DecryptorMessage& decryptor_message);
82 void KeyMessage(int32_t result, const DecryptorMessage& decryptor_message);
83 void KeyError(int32_t result, const DecryptorMessage& decryptor_message);
84 void DeliverBlock(int32_t result, const DecryptedBlock& decrypted_block);
85
86 pp::CompletionCallbackFactory<CDMWrapper> callback_factory_;
87
88 virtual bool IsValidSessionId(std::string session_id) {
89 // TODO(tomfinegan): The CDM MUST handle multiple session IDs. This simple
90 // implementation exists for testing purposes.
91 return (!session_id_.empty() && session_id == session_id_);
92 }
93
94 // TODO(tomfinegan): This needs to be mappable to init data (key IDs in the
95 // WebM case). For WebM it most likely will be 1 key ID and 1 session per
96 // stream. For now we'll just use a random number.
97 uint32_t next_session_id_;
98 std::string session_id_;
xhwang 2012/08/15 00:27:57 Do we need to check in these test code? The CDM wi
Tom Finegan 2012/08/16 03:10:48 Done.
99
100 // Key ID obtained from init data passed to <code>GenerateKeyRequest</code>.
101 // As-is: WebM video specific; Inadequate for WebM with encrypted audio (A/V
102 // will not have same key ID/key/session ID). Probably inadequate for ISO.
103 std::string key_id_;
xhwang 2012/08/15 00:27:57 ditto
Tom Finegan 2012/08/16 03:10:48 Done.
104
105 // TODO(tomfinegan): Should these be multimaps of session_id:key_system and
106 // session_id:key? Or am I completely confused? :)
107 std::string key_;
108 std::string key_system_;
xhwang 2012/08/15 00:27:57 ditto
Tom Finegan 2012/08/16 03:10:48 Done.
109 };
110
111 CDMWrapper::CDMWrapper(PP_Instance instance,
112 pp::Module* module)
113 : pp::Instance(instance),
114 pp::ContentDecryptor_Private(this),
115 next_session_id_(0) {
116 callback_factory_.Initialize(this);
117 }
118
119 bool CDMWrapper::GenerateKeyRequest(const std::string& key_system,
120 pp::VarArrayBuffer init_data) {
121
122 // TODO(tomfinegan): Testing only implementation; init_data will not always
123 // be the key ID.
124 key_id_.assign(reinterpret_cast<char*>(init_data.Map()),
125 init_data.ByteLength());
126 key_system_ = key_system;
127
128 if (key_id_.empty() || key_system_.empty())
129 return false;
130
131 std::ostringstream stream;
132 stream << next_session_id_++;
133 session_id_ = stream.str();
134
135 DecryptorMessage decryptor_message;
136 decryptor_message.key_system = key_system_;
137 decryptor_message.session_id = session_id_;
138 decryptor_message.default_url = "http://www.google.com";
139 decryptor_message.message_data = "key request";
140
141 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::KeyMessage,
142 decryptor_message));
143 return true;
144 }
145
146 bool CDMWrapper::AddKey(const std::string& session_id,
147 pp::VarArrayBuffer key) {
148 if (!IsValidSessionId(session_id))
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(const std::string& session_id) {
162 if (!IsValidSessionId(session_id))
163 return false;
164
165 // TODO(tomfinegan): cancel pending key request in CDM.
166
167 return true;
168 }
169
170 bool CDMWrapper::Decrypt(pp::Buffer_Dev encrypted_block,
171 int32_t request_id) {
172 if (!encrypted_block.data())
173 return false;
174
175 DecryptedBlock decrypted_block;
176 decrypted_block.request_id = request_id;
177 decrypted_block.data = "Pretend I'm decrypted data!";
178 CallOnMain(callback_factory_.NewCallback(&CDMWrapper::DeliverBlock,
179 decrypted_block));
180 return true;
181 }
182
183 PP_Resource CDMWrapper::StringToBufferResource(const std::string& str) {
184 if (str.empty())
185 return 0;
186
187 pp::Buffer_Dev buffer(this, str.size());
188 if (!buffer.data())
189 return 0;
190
191 std::memcpy(buffer.data(), str.data(), str.size());
192 return buffer.detach();
193 }
194
195 void CDMWrapper::NeedKey(int32_t result,
196 const DecryptorMessage& decryptor_message) {
197 pp::ContentDecryptor_Private::NeedKey(decryptor_message.key_system,
198 decryptor_message.session_id,
199 decryptor_message.message_data);
200 }
201
202 void CDMWrapper::KeyAdded(int32_t result,
203 const DecryptorMessage& decryptor_message) {
204 pp::ContentDecryptor_Private::KeyAdded(decryptor_message.key_system,
205 decryptor_message.session_id);
206 }
207
208 void CDMWrapper::KeyMessage(int32_t result,
209 const DecryptorMessage& decryptor_message) {
210 pp::Buffer_Dev message_buffer(
211 StringToBufferResource(decryptor_message.message_data));
212 pp::ContentDecryptor_Private::KeyMessage(decryptor_message.key_system,
213 decryptor_message.session_id,
214 message_buffer,
215 decryptor_message.default_url);
216 }
217
218 void CDMWrapper::KeyError(int32_t result,
219 const DecryptorMessage& decryptor_message) {
220 pp::ContentDecryptor_Private::KeyError(decryptor_message.key_system,
221 decryptor_message.session_id,
222 decryptor_message.media_error,
223 decryptor_message.system_code);
224 }
225
226 void CDMWrapper::DeliverBlock(int32_t result,
227 const DecryptedBlock& decrypted_block) {
228 pp::Buffer_Dev decrypted_buffer(
229 StringToBufferResource(decrypted_block.data));
230 pp::ContentDecryptor_Private::DeliverBlock(decrypted_buffer,
231 decrypted_block.request_id);
232 }
233
234 // This object is the global object representing this plugin library as long
235 // as it is loaded.
236 class MyModule : public pp::Module {
237 public:
238 MyModule() : pp::Module() {}
239 virtual ~MyModule() {}
240
241 virtual pp::Instance* CreateInstance(PP_Instance instance) {
242 return new CDMWrapper(instance, this);
243 }
244 };
245
246 namespace pp {
247
248 // Factory function for your specialization of the Module object.
249 Module* CreateModule() {
250 return new MyModule();
251 }
252
253 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698