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