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

Side by Side Diff: media/cdm/json_web_key.cc

Issue 427993002: Implement ClearKey message format as JSON. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updates Created 6 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "media/cdm/json_web_key.h" 5 #include "media/cdm/json_web_key.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/json/json_string_value_serializer.h" 9 #include "base/json/json_string_value_serializer.h"
10 #include "base/json/string_escape.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 15
15 namespace media { 16 namespace media {
16 17
17 const char kKeysTag[] = "keys"; 18 const char kKeysTag[] = "keys";
18 const char kKeyTypeTag[] = "kty"; 19 const char kKeyTypeTag[] = "kty";
19 const char kSymmetricKeyValue[] = "oct"; 20 const char kSymmetricKeyValue[] = "oct";
20 const char kKeyTag[] = "k"; 21 const char kKeyTag[] = "k";
21 const char kKeyIdTag[] = "kid"; 22 const char kKeyIdTag[] = "kid";
23 const char kKeyIdsTag[] = "kids";
22 const char kBase64Padding = '='; 24 const char kBase64Padding = '=';
25 const char kTypeTag[] = "type";
26 const char kPersistentType[] = "persistent";
27 const char kTemporaryType[] = "temporary";
23 28
24 // Encodes |input| into a base64 string without padding. 29 // Encodes |input| into a base64 string without padding.
25 static std::string EncodeBase64(const uint8* input, int input_length) { 30 static std::string EncodeBase64(const uint8* input, int input_length) {
26 std::string encoded_text; 31 std::string encoded_text;
27 base::Base64Encode( 32 base::Base64Encode(
28 std::string(reinterpret_cast<const char*>(input), input_length), 33 std::string(reinterpret_cast<const char*>(input), input_length),
29 &encoded_text); 34 &encoded_text);
30 35
31 // Remove any padding characters added by Base64Encode(). 36 // Remove any padding characters added by Base64Encode().
32 size_t found = encoded_text.find_last_not_of(kBase64Padding); 37 size_t found = encoded_text.find_last_not_of(kBase64Padding);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 if (raw_key.empty()) { 118 if (raw_key.empty()) {
114 DVLOG(1) << "Invalid '" << kKeyTag << "' value: " << encoded_key; 119 DVLOG(1) << "Invalid '" << kKeyTag << "' value: " << encoded_key;
115 return false; 120 return false;
116 } 121 }
117 122
118 // Add the decoded key ID and the decoded key to the list. 123 // Add the decoded key ID and the decoded key to the list.
119 *jwk_key = std::make_pair(raw_key_id, raw_key); 124 *jwk_key = std::make_pair(raw_key_id, raw_key);
120 return true; 125 return true;
121 } 126 }
122 127
123 bool ExtractKeysFromJWKSet(const std::string& jwk_set, KeyIdAndKeyPairs* keys) { 128 bool ExtractKeysFromJWKSet(const std::string& jwk_set,
129 KeyIdAndKeyPairs* keys,
130 MediaKeys::SessionType* session_type) {
124 if (!base::IsStringASCII(jwk_set)) 131 if (!base::IsStringASCII(jwk_set))
125 return false; 132 return false;
126 133
127 scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(jwk_set)); 134 scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(jwk_set));
128 if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) 135 if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY)
129 return false; 136 return false;
130 137
131 // Locate the set from the dictionary. 138 // Locate the set from the dictionary.
132 base::DictionaryValue* dictionary = 139 base::DictionaryValue* dictionary =
133 static_cast<base::DictionaryValue*>(root.get()); 140 static_cast<base::DictionaryValue*>(root.get());
(...skipping 15 matching lines...) Expand all
149 return false; 156 return false;
150 } 157 }
151 KeyIdAndKeyPair key_pair; 158 KeyIdAndKeyPair key_pair;
152 if (!ConvertJwkToKeyPair(*jwk, &key_pair)) { 159 if (!ConvertJwkToKeyPair(*jwk, &key_pair)) {
153 DVLOG(1) << "Error from '" << kKeysTag << "'[" << i << "]"; 160 DVLOG(1) << "Error from '" << kKeysTag << "'[" << i << "]";
154 return false; 161 return false;
155 } 162 }
156 local_keys.push_back(key_pair); 163 local_keys.push_back(key_pair);
157 } 164 }
158 165
159 // Successfully processed all JWKs in the set. 166 // Successfully processed all JWKs in the set. Now check if "type" is
167 // specified.
168 base::Value* value = NULL;
169 std::string type_id;
170 if (!dictionary->Get(kTypeTag, &value)) {
171 // Not specified, so use the default type.
172 *session_type = MediaKeys::TEMPORARY_SESSION;
173 } else if (!value->GetAsString(&type_id)) {
174 DVLOG(1) << "Invalid '" << kTypeTag << "' value";
175 return false;
176 } else if (type_id == kPersistentType) {
177 *session_type = MediaKeys::PERSISTENT_SESSION;
178 } else if (type_id == kTemporaryType) {
179 *session_type = MediaKeys::TEMPORARY_SESSION;
180 } else {
181 DVLOG(1) << "Invalid '" << kTypeTag << "' value: " << type_id;
182 return false;
183 }
184
185 // All done.
160 keys->swap(local_keys); 186 keys->swap(local_keys);
161 return true; 187 return true;
162 } 188 }
163 189
190 void CreateLicenseRequest(const uint8* key_id,
191 int key_id_length,
192 MediaKeys::SessionType session_type,
193 std::vector<uint8>* license) {
194 // Create the license request.
195 scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue());
196 scoped_ptr<base::ListValue> list(new base::ListValue());
197 list->AppendString(EncodeBase64(key_id, key_id_length));
198 request->Set(kKeyIdsTag, list.release());
199
200 switch (session_type) {
201 case MediaKeys::TEMPORARY_SESSION:
202 request->SetString(kTypeTag, kTemporaryType);
203 break;
204 case MediaKeys::PERSISTENT_SESSION:
205 request->SetString(kTypeTag, kPersistentType);
206 break;
207 }
208
209 // Serialize the license request as a string.
210 std::string json;
211 JSONStringValueSerializer serializer(&json);
212 serializer.Serialize(*request);
213
214 // Convert the serialized license request into std::vector and return it.
215 std::vector<uint8> result(json.begin(), json.end());
216 license->swap(result);
217 }
218
219 bool ExtractFirstKeyIdFromLicenseRequest(const std::vector<uint8>& license,
220 std::vector<uint8>* first_key) {
221 const std::string license_as_str(
222 reinterpret_cast<const char*>(license.data()), license.size());
xhwang 2014/08/08 20:31:12 vector::data() is a c++11 feature which we don't s
jrummell 2014/08/09 00:14:17 Done.
223 if (!base::IsStringASCII(license_as_str))
224 return false;
225
226 scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(license_as_str));
227 if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY)
228 return false;
229
230 // Locate the set from the dictionary.
231 base::DictionaryValue* dictionary =
232 static_cast<base::DictionaryValue*>(root.get());
233 base::ListValue* list_val = NULL;
234 if (!dictionary->GetList(kKeyIdsTag, &list_val)) {
235 DVLOG(1) << "Missing '" << kKeyIdsTag << "' parameter or not a list";
236 return false;
237 }
238
239 // Get the first key.
240 if (list_val->GetSize() < 1) {
241 DVLOG(1) << "Empty '" << kKeyIdsTag << "' list";
242 return false;
243 }
244
245 std::string encoded_key;
246 if (!list_val->GetString(0, &encoded_key)) {
247 DVLOG(1) << "First entry in '" << kKeyIdsTag << "' not a string";
248 return false;
249 }
250
251 std::string decoded_string = DecodeBase64(encoded_key);
252 if (decoded_string.empty()) {
253 DVLOG(1) << "Invalid '" << kKeyIdsTag << "' value: " << encoded_key;
254 return false;
255 }
256
257 std::vector<uint8> result(decoded_string.begin(), decoded_string.end());
258 first_key->swap(result);
259 return true;
260 }
261
164 } // namespace media 262 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698