Chromium Code Reviews| Index: media/cdm/json_web_key.cc |
| diff --git a/media/cdm/json_web_key.cc b/media/cdm/json_web_key.cc |
| index 4b9d8221f764ce8364b2000813fddb1ed583bcfb..500590b9458ad5029779d272ff8f61259a6ab784 100644 |
| --- a/media/cdm/json_web_key.cc |
| +++ b/media/cdm/json_web_key.cc |
| @@ -7,6 +7,7 @@ |
| #include "base/base64.h" |
| #include "base/json/json_reader.h" |
| #include "base/json/json_string_value_serializer.h" |
| +#include "base/json/string_escape.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/strings/string_util.h" |
| @@ -19,7 +20,11 @@ const char kKeyTypeTag[] = "kty"; |
| const char kSymmetricKeyValue[] = "oct"; |
| const char kKeyTag[] = "k"; |
| const char kKeyIdTag[] = "kid"; |
| +const char kKeyIdsTag[] = "kids"; |
| const char kBase64Padding = '='; |
| +const char kTypeTag[] = "type"; |
| +const char kPersistentType[] = "persistent"; |
| +const char kTemporaryType[] = "temporary"; |
| // Encodes |input| into a base64 string without padding. |
| static std::string EncodeBase64(const uint8* input, int input_length) { |
| @@ -120,7 +125,9 @@ static bool ConvertJwkToKeyPair(const base::DictionaryValue& jwk, |
| return true; |
| } |
| -bool ExtractKeysFromJWKSet(const std::string& jwk_set, KeyIdAndKeyPairs* keys) { |
| +bool ExtractKeysFromJWKSet(const std::string& jwk_set, |
| + KeyIdAndKeyPairs* keys, |
| + MediaKeys::SessionType* session_type) { |
| if (!base::IsStringASCII(jwk_set)) |
| return false; |
| @@ -156,9 +163,100 @@ bool ExtractKeysFromJWKSet(const std::string& jwk_set, KeyIdAndKeyPairs* keys) { |
| local_keys.push_back(key_pair); |
| } |
| - // Successfully processed all JWKs in the set. |
| + // Successfully processed all JWKs in the set. Now check if "type" is |
| + // specified. |
| + base::Value* value = NULL; |
| + std::string type_id; |
| + if (!dictionary->Get(kTypeTag, &value)) { |
| + // Not specified, so use the default type. |
| + *session_type = MediaKeys::TEMPORARY_SESSION; |
| + } else if (!value->GetAsString(&type_id)) { |
| + DVLOG(1) << "Invalid '" << kTypeTag << "' value"; |
| + return false; |
| + } else if (type_id == kPersistentType) { |
| + *session_type = MediaKeys::PERSISTENT_SESSION; |
| + } else if (type_id == kTemporaryType) { |
| + *session_type = MediaKeys::TEMPORARY_SESSION; |
| + } else { |
| + DVLOG(1) << "Invalid '" << kTypeTag << "' value: " << type_id; |
| + return false; |
| + } |
| + |
| + // All done. |
| keys->swap(local_keys); |
| return true; |
| } |
| +void CreateLicenseRequest(const uint8* key_id, |
| + int key_id_length, |
| + MediaKeys::SessionType session_type, |
| + std::vector<uint8>* license) { |
| + // Create the license request. |
| + scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue()); |
| + scoped_ptr<base::ListValue> list(new base::ListValue()); |
| + list->AppendString(EncodeBase64(key_id, key_id_length)); |
| + request->Set(kKeyIdsTag, list.release()); |
| + |
| + switch (session_type) { |
| + case MediaKeys::TEMPORARY_SESSION: |
| + request->SetString(kTypeTag, kTemporaryType); |
| + break; |
| + case MediaKeys::PERSISTENT_SESSION: |
| + request->SetString(kTypeTag, kPersistentType); |
| + break; |
| + } |
| + |
| + // Serialize the license request as a string. |
| + std::string json; |
| + JSONStringValueSerializer serializer(&json); |
| + serializer.Serialize(*request); |
| + |
| + // Convert the serialized license request into std::vector and return it. |
| + std::vector<uint8> result(json.begin(), json.end()); |
| + license->swap(result); |
| +} |
| + |
| +bool ExtractFirstKeyIdFromLicenseRequest(const std::vector<uint8>& license, |
| + std::vector<uint8>* first_key) { |
| + const std::string license_as_str( |
| + 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.
|
| + if (!base::IsStringASCII(license_as_str)) |
| + return false; |
| + |
| + scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(license_as_str)); |
| + if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) |
| + return false; |
| + |
| + // Locate the set from the dictionary. |
| + base::DictionaryValue* dictionary = |
| + static_cast<base::DictionaryValue*>(root.get()); |
| + base::ListValue* list_val = NULL; |
| + if (!dictionary->GetList(kKeyIdsTag, &list_val)) { |
| + DVLOG(1) << "Missing '" << kKeyIdsTag << "' parameter or not a list"; |
| + return false; |
| + } |
| + |
| + // Get the first key. |
| + if (list_val->GetSize() < 1) { |
| + DVLOG(1) << "Empty '" << kKeyIdsTag << "' list"; |
| + return false; |
| + } |
| + |
| + std::string encoded_key; |
| + if (!list_val->GetString(0, &encoded_key)) { |
| + DVLOG(1) << "First entry in '" << kKeyIdsTag << "' not a string"; |
| + return false; |
| + } |
| + |
| + std::string decoded_string = DecodeBase64(encoded_key); |
| + if (decoded_string.empty()) { |
| + DVLOG(1) << "Invalid '" << kKeyIdsTag << "' value: " << encoded_key; |
| + return false; |
| + } |
| + |
| + std::vector<uint8> result(decoded_string.begin(), decoded_string.end()); |
| + first_key->swap(result); |
| + return true; |
| +} |
| + |
| } // namespace media |