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
3 // found in the LICENSE file.
5 #include "media/cdm/json_web_key.h"
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "testing/gtest/include/gtest/gtest.h"
13 class JSONWebKeyTest
: public testing::Test
{
18 void ExtractJWKKeysAndExpect(const std::string
& jwk
,
20 size_t expected_number_of_keys
) {
22 KeyIdAndKeyPairs keys
;
23 MediaKeys::SessionType session_type
;
24 EXPECT_EQ(expected_result
,
25 ExtractKeysFromJWKSet(jwk
, &keys
, &session_type
));
26 EXPECT_EQ(expected_number_of_keys
, keys
.size());
29 void ExtractSessionTypeAndExpect(const std::string
& jwk
,
31 MediaKeys::SessionType expected_type
) {
33 KeyIdAndKeyPairs keys
;
34 MediaKeys::SessionType session_type
;
35 EXPECT_EQ(expected_result
,
36 ExtractKeysFromJWKSet(jwk
, &keys
, &session_type
));
37 if (expected_result
) {
38 // Only check if successful.
39 EXPECT_EQ(expected_type
, session_type
);
43 void CreateLicenseAndExpect(const uint8
* key_id
,
45 MediaKeys::SessionType session_type
,
46 const std::string
& expected_result
) {
47 std::vector
<uint8
> result
;
49 key_ids
.push_back(std::vector
<uint8
>(key_id
, key_id
+ key_id_length
));
50 CreateLicenseRequest(key_ids
, session_type
, &result
);
51 std::string
s(result
.begin(), result
.end());
52 EXPECT_EQ(expected_result
, s
);
55 void ExtractKeyFromLicenseAndExpect(const std::string
& license
,
57 const uint8
* expected_key
,
58 int expected_key_length
) {
59 std::vector
<uint8
> license_vector(license
.begin(), license
.end());
60 std::vector
<uint8
> key
;
61 EXPECT_EQ(expected_result
,
62 ExtractFirstKeyIdFromLicenseRequest(license_vector
, &key
));
64 VerifyKeyId(key
, expected_key
, expected_key_length
);
67 void VerifyKeyId(std::vector
<uint8
> key
,
68 const uint8
* expected_key
,
69 int expected_key_length
) {
70 std::vector
<uint8
> key_result(expected_key
,
71 expected_key
+ expected_key_length
);
72 EXPECT_EQ(key_result
, key
);
76 TEST_F(JSONWebKeyTest
, GenerateJWKSet
) {
77 const uint8 data1
[] = { 0x01, 0x02 };
78 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
79 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
80 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
83 "{\"keys\":[{\"alg\":\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":"
85 GenerateJWKSet(data1
, arraysize(data1
), data1
, arraysize(data1
)));
87 "{\"keys\":[{\"alg\":\"A128KW\",\"k\":\"AQIDBA\",\"kid\":\"AQIDBA\","
89 GenerateJWKSet(data2
, arraysize(data2
), data2
, arraysize(data2
)));
91 "{\"keys\":[{\"alg\":\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQIDBA\",\"kty\":"
93 GenerateJWKSet(data1
, arraysize(data1
), data2
, arraysize(data2
)));
95 "{\"keys\":[{\"alg\":\"A128KW\",\"k\":\"AQIDBA\",\"kid\":\"AQI\",\"kty\":"
97 GenerateJWKSet(data2
, arraysize(data2
), data1
, arraysize(data1
)));
99 "{\"keys\":[{\"alg\":\"A128KW\",\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":"
100 "\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kty\":\"oct\"}]}",
101 GenerateJWKSet(data3
, arraysize(data3
), data3
, arraysize(data3
)));
104 TEST_F(JSONWebKeyTest
, ExtractValidJWKKeys
) {
105 // Try an empty 'keys' dictionary.
106 ExtractJWKKeysAndExpect("{ \"keys\": [] }", true, 0);
108 // Try a key list with one entry.
109 const std::string kJwksOneEntry
=
114 " \"alg\": \"A128KW\","
115 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
116 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
120 ExtractJWKKeysAndExpect(kJwksOneEntry
, true, 1);
122 // Try a key list with multiple entries.
123 const std::string kJwksMultipleEntries
=
128 " \"alg\": \"A128KW\","
129 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
130 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
134 " \"alg\": \"A128KW\","
135 " \"kid\": \"JCUmJygpKissLS4vMA\","
136 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
140 ExtractJWKKeysAndExpect(kJwksMultipleEntries
, true, 2);
142 // Try a key with no spaces and some \n plus additional fields.
143 const std::string kJwksNoSpaces
=
144 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
145 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
146 "\",\"foo\":\"bar\"}]}\n\n";
147 ExtractJWKKeysAndExpect(kJwksNoSpaces
, true, 1);
149 // Try a list with multiple keys with the same kid.
150 const std::string kJwksDuplicateKids
=
155 " \"alg\": \"A128KW\","
156 " \"kid\": \"JCUmJygpKissLS4vMA\","
157 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
161 " \"alg\": \"A128KW\","
162 " \"kid\": \"JCUmJygpKissLS4vMA\","
163 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
167 ExtractJWKKeysAndExpect(kJwksDuplicateKids
, true, 2);
170 TEST_F(JSONWebKeyTest
, ExtractInvalidJWKKeys
) {
171 // Try a simple JWK key (i.e. not in a set)
172 const std::string kJwkSimple
=
175 " \"alg\": \"A128KW\","
176 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
177 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
179 ExtractJWKKeysAndExpect(kJwkSimple
, false, 0);
181 // Try some non-ASCII characters.
182 ExtractJWKKeysAndExpect(
183 "This is not ASCII due to \xff\xfe\xfd in it.", false, 0);
185 // Try some non-ASCII characters in an otherwise valid JWK.
186 const std::string kJwksInvalidCharacters
=
187 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
188 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"\xff\xfe\xfd"
189 "\",\"foo\":\"bar\"}]}\n\n";
190 ExtractJWKKeysAndExpect(kJwksInvalidCharacters
, false, 0);
192 // Try a badly formatted key. Assume that the JSON parser is fully tested,
193 // so we won't try a lot of combinations. However, need a test to ensure
194 // that the code doesn't crash if invalid JSON received.
195 ExtractJWKKeysAndExpect("This is not a JSON key.", false, 0);
197 // Try passing some valid JSON that is not a dictionary at the top level.
198 ExtractJWKKeysAndExpect("40", false, 0);
200 // Try an empty dictionary.
201 ExtractJWKKeysAndExpect("{ }", false, 0);
203 // Try with 'keys' not a dictionary.
204 ExtractJWKKeysAndExpect("{ \"keys\":\"1\" }", false, 0);
206 // Try with 'keys' a list of integers.
207 ExtractJWKKeysAndExpect("{ \"keys\": [ 1, 2, 3 ] }", false, 0);
209 // Try padding(=) at end of 'k' base64 string.
210 const std::string kJwksWithPaddedKey
=
215 " \"alg\": \"A128KW\","
216 " \"kid\": \"AAECAw\","
217 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
221 ExtractJWKKeysAndExpect(kJwksWithPaddedKey
, false, 0);
223 // Try padding(=) at end of 'kid' base64 string.
224 const std::string kJwksWithPaddedKeyId
=
229 " \"alg\": \"A128KW\","
230 " \"kid\": \"AAECAw==\","
231 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
235 ExtractJWKKeysAndExpect(kJwksWithPaddedKeyId
, false, 0);
237 // Try a key with invalid base64 encoding.
238 const std::string kJwksWithInvalidBase64
=
243 " \"alg\": \"A128KW\","
244 " \"kid\": \"!@#$%^&*()\","
245 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
249 ExtractJWKKeysAndExpect(kJwksWithInvalidBase64
, false, 0);
252 const std::string kJwksWithEmptyKeyId
=
257 " \"alg\": \"A128KW\","
259 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
263 ExtractJWKKeysAndExpect(kJwksWithEmptyKeyId
, false, 0);
266 TEST_F(JSONWebKeyTest
, KeyType
) {
268 const std::string kJwksWithValidKeyType
=
273 " \"alg\": \"A128KW\","
274 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
275 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
279 ExtractJWKKeysAndExpect(kJwksWithValidKeyType
, true, 1);
282 const std::string kJwksWithEmptyKeyType
=
287 " \"alg\": \"A128KW\","
288 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
289 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
293 ExtractJWKKeysAndExpect(kJwksWithEmptyKeyType
, false, 0);
295 // Key type is case sensitive.
296 const std::string kJwksWithUppercaseKeyType
=
301 " \"alg\": \"A128KW\","
302 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
303 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
307 ExtractJWKKeysAndExpect(kJwksWithUppercaseKeyType
, false, 0);
310 const std::string kJwksWithWrongKeyType
=
315 " \"alg\": \"A128KW\","
316 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
317 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
321 ExtractJWKKeysAndExpect(kJwksWithWrongKeyType
, false, 0);
324 TEST_F(JSONWebKeyTest
, Alg
) {
326 const std::string kJwksWithValidAlg
=
331 " \"alg\": \"A128KW\","
332 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
333 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
337 ExtractJWKKeysAndExpect(kJwksWithValidAlg
, true, 1);
340 const std::string kJwksWithEmptyAlg
=
346 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
347 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
351 ExtractJWKKeysAndExpect(kJwksWithEmptyAlg
, false, 0);
353 // Alg is case sensitive.
354 const std::string kJwksWithLowercaseAlg
=
359 " \"alg\": \"a128kw\","
360 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
361 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
365 ExtractJWKKeysAndExpect(kJwksWithLowercaseAlg
, false, 0);
368 const std::string kJwksWithWrongAlg
=
373 " \"alg\": \"RS256\","
374 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
375 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
379 ExtractJWKKeysAndExpect(kJwksWithWrongAlg
, false, 0);
382 TEST_F(JSONWebKeyTest
, SessionType
) {
383 ExtractSessionTypeAndExpect(
384 "{\"keys\":[{\"alg\": "
385 "\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
386 true, MediaKeys::TEMPORARY_SESSION
);
387 ExtractSessionTypeAndExpect(
388 "{\"keys\":[{\"alg\": "
389 "\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
391 true, MediaKeys::TEMPORARY_SESSION
);
392 ExtractSessionTypeAndExpect(
393 "{\"keys\":[{\"alg\": "
394 "\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
395 "\"persistent-license\"}",
396 true, MediaKeys::PERSISTENT_LICENSE_SESSION
);
397 ExtractSessionTypeAndExpect(
398 "{\"keys\":[{\"alg\": "
399 "\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
400 "\"persistent-release-message\"}",
401 true, MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION
);
402 ExtractSessionTypeAndExpect(
403 "{\"keys\":[{\"alg\": "
404 "\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
406 false, MediaKeys::TEMPORARY_SESSION
);
407 ExtractSessionTypeAndExpect(
408 "{\"keys\":[{\"alg\": "
409 "\"A128KW\",\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":3}",
410 false, MediaKeys::TEMPORARY_SESSION
);
413 TEST_F(JSONWebKeyTest
, CreateLicense
) {
414 const uint8 data1
[] = { 0x01, 0x02 };
415 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
416 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
417 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
419 CreateLicenseAndExpect(data1
,
421 MediaKeys::TEMPORARY_SESSION
,
422 "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}");
423 CreateLicenseAndExpect(
424 data1
, arraysize(data1
), MediaKeys::PERSISTENT_LICENSE_SESSION
,
425 "{\"kids\":[\"AQI\"],\"type\":\"persistent-license\"}");
426 CreateLicenseAndExpect(
427 data1
, arraysize(data1
), MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION
,
428 "{\"kids\":[\"AQI\"],\"type\":\"persistent-release-message\"}");
429 CreateLicenseAndExpect(data2
,
431 MediaKeys::TEMPORARY_SESSION
,
432 "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}");
433 CreateLicenseAndExpect(data3
, arraysize(data3
),
434 MediaKeys::PERSISTENT_LICENSE_SESSION
,
435 "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":"
436 "\"persistent-license\"}");
439 TEST_F(JSONWebKeyTest
, ExtractLicense
) {
440 const uint8 data1
[] = { 0x01, 0x02 };
441 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
442 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
443 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
445 ExtractKeyFromLicenseAndExpect(
446 "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}",
450 ExtractKeyFromLicenseAndExpect(
451 "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}",
455 ExtractKeyFromLicenseAndExpect(
456 "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":\"persistent\"}",
461 // Try some incorrect JSON.
462 ExtractKeyFromLicenseAndExpect("", false, NULL
, 0);
463 ExtractKeyFromLicenseAndExpect("!@#$%^&*()", false, NULL
, 0);
465 // Valid JSON, but not a dictionary.
466 ExtractKeyFromLicenseAndExpect("6", false, NULL
, 0);
467 ExtractKeyFromLicenseAndExpect("[\"AQI\"]", false, NULL
, 0);
469 // Dictionary, but missing expected tag.
470 ExtractKeyFromLicenseAndExpect("{\"kid\":[\"AQI\"]}", false, NULL
, 0);
472 // Correct tag, but empty list.
473 ExtractKeyFromLicenseAndExpect("{\"kids\":[]}", false, NULL
, 0);
475 // Correct tag, but list doesn't contain a string.
476 ExtractKeyFromLicenseAndExpect("{\"kids\":[[\"AQI\"]]}", false, NULL
, 0);
478 // Correct tag, but invalid base64 encoding.
479 ExtractKeyFromLicenseAndExpect("{\"kids\":[\"!@#$%^&*()\"]}", false, NULL
, 0);
482 TEST_F(JSONWebKeyTest
, Base64UrlEncoding
) {
483 const uint8 data1
[] = { 0xfb, 0xfd, 0xfb, 0xfd, 0xfb, 0xfd, 0xfb };
485 // Verify that |data1| contains invalid base64url characters '+' and '/'
486 // and is padded with = when converted to base64.
487 std::string encoded_text
;
489 std::string(reinterpret_cast<const char*>(&data1
[0]), arraysize(data1
)),
491 EXPECT_EQ(encoded_text
, "+/37/fv9+w==");
492 EXPECT_NE(encoded_text
.find('+'), std::string::npos
);
493 EXPECT_NE(encoded_text
.find('/'), std::string::npos
);
494 EXPECT_NE(encoded_text
.find('='), std::string::npos
);
496 // base64url characters '-' and '_' not in base64 encoding.
497 EXPECT_EQ(encoded_text
.find('-'), std::string::npos
);
498 EXPECT_EQ(encoded_text
.find('_'), std::string::npos
);
500 CreateLicenseAndExpect(data1
, arraysize(data1
), MediaKeys::TEMPORARY_SESSION
,
501 "{\"kids\":[\"-_37_fv9-w\"],\"type\":\"temporary\"}");
503 ExtractKeyFromLicenseAndExpect(
504 "{\"kids\":[\"-_37_fv9-w\"],\"type\":\"temporary\"}", true, data1
,
508 TEST_F(JSONWebKeyTest
, MultipleKeys
) {
509 const uint8 data1
[] = { 0x01, 0x02 };
510 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
511 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
512 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
514 std::vector
<uint8
> result
;
516 key_ids
.push_back(std::vector
<uint8
>(data1
, data1
+ arraysize(data1
)));
517 key_ids
.push_back(std::vector
<uint8
>(data2
, data2
+ arraysize(data2
)));
518 key_ids
.push_back(std::vector
<uint8
>(data3
, data3
+ arraysize(data3
)));
519 CreateLicenseRequest(key_ids
, MediaKeys::TEMPORARY_SESSION
, &result
);
520 std::string
s(result
.begin(), result
.end());
522 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":"
527 TEST_F(JSONWebKeyTest
, ExtractKeyIds
) {
528 const uint8 data1
[] = { 0x01, 0x02 };
529 const uint8 data2
[] = { 0x01, 0x02, 0x03, 0x04 };
530 const uint8 data3
[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
531 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
534 std::string error_message
;
536 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI\"]}", &key_ids
,
538 EXPECT_EQ(1u, key_ids
.size());
539 EXPECT_EQ(0u, error_message
.length());
540 VerifyKeyId(key_ids
[0], data1
, arraysize(data1
));
542 EXPECT_TRUE(ExtractKeyIdsFromKeyIdsInitData(
543 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"]}", &key_ids
,
545 EXPECT_EQ(3u, key_ids
.size());
546 EXPECT_EQ(0u, error_message
.length());
547 VerifyKeyId(key_ids
[0], data1
, arraysize(data1
));
548 VerifyKeyId(key_ids
[1], data2
, arraysize(data2
));
549 VerifyKeyId(key_ids
[2], data3
, arraysize(data3
));
551 // Expect failure when non-ascii.
552 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData(
553 "This is not ASCII due to \xff\xfe\x0a in it.", &key_ids
,
555 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
556 EXPECT_EQ(error_message
,
557 "Non ASCII: This is not ASCII due to \\u00FF\\u00FE\\n in it.");
559 // Expect failure when not JSON or not a dictionary.
560 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("This is invalid.", &key_ids
,
562 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
563 EXPECT_EQ(error_message
, "Not valid JSON: This is invalid.");
564 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("6", &key_ids
, &error_message
));
565 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
566 EXPECT_EQ(error_message
, "Not valid JSON: 6");
567 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData(
568 "This is a very long string that is longer than 64 characters and is "
570 &key_ids
, &error_message
));
571 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
572 EXPECT_EQ(error_message
,
573 "Not valid JSON: This is a very long string that is longer than 64 "
576 // Expect failure when "kids" not specified.
577 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"keys\":[\"AQI\"]}", &key_ids
,
579 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
580 EXPECT_EQ(error_message
, "Missing 'kids' parameter or not a list");
582 // Expect failure when invalid key_ids specified.
583 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[1]}", &key_ids
,
585 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
586 EXPECT_EQ(error_message
, "'kids'[0] is not string.");
587 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\": {\"id\":\"AQI\" }}",
588 &key_ids
, &error_message
));
589 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
590 EXPECT_EQ(error_message
, "Missing 'kids' parameter or not a list");
592 // Expect failure when non-base64 key_ids specified.
593 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI+\"]}",
594 &key_ids
, &error_message
));
595 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
596 EXPECT_EQ(error_message
,
597 "'kids'[0] is not valid base64url encoded. Value: AQI+");
598 EXPECT_FALSE(ExtractKeyIdsFromKeyIdsInitData("{\"kids\":[\"AQI\",\"AQI/\"]}",
599 &key_ids
, &error_message
));
600 EXPECT_EQ(3u, key_ids
.size()); // |key_ids| should be unchanged.
601 EXPECT_EQ(error_message
,
602 "'kids'[1] is not valid base64url encoded. Value: AQI/");