1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/cdm/json_web_key.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/base64.h" 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/json/json_reader.h" 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/json/json_string_value_serializer.h" 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/json/string_escape.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/string_util.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/values.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace media { 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kKeysTag[] = "keys"; 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kKeyTypeTag[] = "kty"; 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kSymmetricKeyValue[] = "oct"; 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kKeyTag[] = "k"; 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kKeyIdTag[] = "kid"; 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kKeyIdsTag[] = "kids"; 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kBase64Padding = '='; 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kTypeTag[] = "type"; 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kPersistentType[] = "persistent"; 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char kTemporaryType[] = "temporary"; 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Encodes |input| into a base64 string without padding. 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static std::string EncodeBase64(const uint8* input, int input_length) { 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string encoded_text; 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Base64Encode( 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string(reinterpret_cast<const char*>(input), input_length), 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &encoded_text); 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Remove any padding characters added by Base64Encode(). 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t found = encoded_text.find_last_not_of(kBase64Padding); 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (found != std::string::npos) 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) encoded_text.erase(found + 1); 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return encoded_text; 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Decodes an unpadded base64 string. Returns empty string on error. 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static std::string DecodeBase64(const std::string& encoded_text) { 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // EME spec doesn't allow padding characters. 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (encoded_text.find_first_of(kBase64Padding) != std::string::npos) 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return std::string(); 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Since base::Base64Decode() requires padding characters, add them so length 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // of |encoded_text| is exactly a multiple of 4. 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t num_last_grouping_chars = encoded_text.length() % 4; 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string modified_text = encoded_text; 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (num_last_grouping_chars > 0) 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modified_text.append(4 - num_last_grouping_chars, kBase64Padding); 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string decoded_text; 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!base::Base64Decode(modified_text, &decoded_text)) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return std::string(); 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return decoded_text; 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string GenerateJWKSet(const uint8* key, int key_length, 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const uint8* key_id, int key_id_length) { 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Both |key| and |key_id| need to be base64 encoded strings in the JWK. 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string key_base64 = EncodeBase64(key, key_length); 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string key_id_base64 = EncodeBase64(key_id, key_id_length); 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Create the JWK, and wrap it into a JWK Set. 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue()); 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) jwk->SetString(kKeyTypeTag, kSymmetricKeyValue); 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) jwk->SetString(kKeyTag, key_base64); 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) jwk->SetString(kKeyIdTag, key_id_base64); 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<base::ListValue> list(new base::ListValue()); 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) list->Append(jwk.release()); 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::DictionaryValue jwk_set; 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) jwk_set.Set(kKeysTag, list.release()); 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Finally serialize |jwk_set| into a string and return it. 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string serialized_jwk; 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) JSONStringValueSerializer serializer(&serialized_jwk); 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) serializer.Serialize(jwk_set); 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return serialized_jwk; 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Processes a JSON Web Key to extract the key id and key value. Sets |jwk_key| 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// to the id/value pair and returns true on success. 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static bool ConvertJwkToKeyPair(const base::DictionaryValue& jwk, 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) KeyIdAndKeyPair* jwk_key) { 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Have found a JWK, start by checking that it is a symmetric key. 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string type; 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!jwk.GetString(kKeyTypeTag, &type) || type != kSymmetricKeyValue) { 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "JWK is not a symmetric key"; 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Get the key id and actual key parameters. 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string encoded_key_id; 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string encoded_key; 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!jwk.GetString(kKeyIdTag, &encoded_key_id)) { 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Missing '" << kKeyIdTag << "' parameter"; 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!jwk.GetString(kKeyTag, &encoded_key)) { 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Missing '" << kKeyTag << "' parameter"; 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Key ID and key are base64-encoded strings, so decode them. 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string raw_key_id = DecodeBase64(encoded_key_id); 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (raw_key_id.empty()) { 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Invalid '" << kKeyIdTag << "' value: " << encoded_key_id; 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string raw_key = DecodeBase64(encoded_key); 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (raw_key.empty()) { 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Invalid '" << kKeyTag << "' value: " << encoded_key; 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Add the decoded key ID and the decoded key to the list. 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *jwk_key = std::make_pair(raw_key_id, raw_key); 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ExtractKeysFromJWKSet(const std::string& jwk_set, 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) KeyIdAndKeyPairs* keys, 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MediaKeys::SessionType* session_type) { 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!base::IsStringASCII(jwk_set)) 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(jwk_set)); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Locate the set from the dictionary. 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dictionary = 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<base::DictionaryValue*>(root.get()); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* list_val = NULL; 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!dictionary->GetList(kKeysTag, &list_val)) { 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Missing '" << kKeysTag 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << "' parameter or not a list in JWK Set"; 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Create a local list of keys, so that |jwk_keys| only gets updated on 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // success. 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) KeyIdAndKeyPairs local_keys; 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t i = 0; i < list_val->GetSize(); ++i) { 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* jwk = NULL; 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!list_val->GetDictionary(i, &jwk)) { 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Unable to access '" << kKeysTag << "'[" << i 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << "] in JWK Set"; 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) KeyIdAndKeyPair key_pair; 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!ConvertJwkToKeyPair(*jwk, &key_pair)) { 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Error from '" << kKeysTag << "'[" << i << "]"; 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) local_keys.push_back(key_pair); 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Successfully processed all JWKs in the set. Now check if "type" is 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // specified. 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Value* value = NULL; 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string type_id; 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!dictionary->Get(kTypeTag, &value)) { 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Not specified, so use the default type. 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *session_type = MediaKeys::TEMPORARY_SESSION; 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (!value->GetAsString(&type_id)) { 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(1) << "Invalid '" << kTypeTag << "' value"; 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (type_id == kPersistentType) { 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *session_type = MediaKeys::PERSISTENT_SESSION; 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (type_id == kTemporaryType) { 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *session_type = MediaKeys::TEMPORARY_SESSION; 18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(1) << "Invalid '" << kTypeTag << "' value: " << type_id; 18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // All done. 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) keys->swap(local_keys); 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CreateLicenseRequest(const uint8* key_id, 19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int key_id_length, 19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MediaKeys::SessionType session_type, 19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::vector<uint8>* license) { 19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Create the license request. 19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue()); 19603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<base::ListValue> list(new base::ListValue()); 19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) list->AppendString(EncodeBase64(key_id, key_id_length)); 19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) request->Set(kKeyIdsTag, list.release()); 19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) switch (session_type) { 20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) case MediaKeys::TEMPORARY_SESSION: 20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) request->SetString(kTypeTag, kTemporaryType); 20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 20403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) case MediaKeys::PERSISTENT_SESSION: 20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) request->SetString(kTypeTag, kPersistentType); 20603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Serialize the license request as a string. 21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string json; 21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) JSONStringValueSerializer serializer(&json); 21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) serializer.Serialize(*request); 21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Convert the serialized license request into std::vector and return it. 21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::vector<uint8> result(json.begin(), json.end()); 21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) license->swap(result); 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ExtractFirstKeyIdFromLicenseRequest(const std::vector<uint8>& license, 22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::vector<uint8>* first_key) { 22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::string license_as_str( 22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) reinterpret_cast<const char*>(!license.empty() ? &license[0] : NULL), 22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) license.size()); 22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!base::IsStringASCII(license_as_str)) 22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(license_as_str)); 22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) 22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Locate the set from the dictionary. 23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* dictionary = 23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static_cast<base::DictionaryValue*>(root.get()); 23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::ListValue* list_val = NULL; 23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!dictionary->GetList(kKeyIdsTag, &list_val)) { 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(1) << "Missing '" << kKeyIdsTag << "' parameter or not a list"; 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Get the first key. 24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (list_val->GetSize() < 1) { 24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(1) << "Empty '" << kKeyIdsTag << "' list"; 24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string encoded_key; 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!list_val->GetString(0, &encoded_key)) { 24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(1) << "First entry in '" << kKeyIdsTag << "' not a string"; 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string decoded_string = DecodeBase64(encoded_key); 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (decoded_string.empty()) { 25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(1) << "Invalid '" << kKeyIdsTag << "' value: " << encoded_key; 25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::vector<uint8> result(decoded_string.begin(), decoded_string.end()); 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) first_key->swap(result); 26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace media 264