| OLD | NEW |
| 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 <string> | 5 #include <string> |
| 6 #include <vector> | 6 #include <vector> |
| 7 | 7 |
| 8 #include "content/renderer/media/crypto/key_systems.h" | 8 #include "content/renderer/media/crypto/key_systems.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 #include "third_party/WebKit/public/platform/WebString.h" | 10 #include "third_party/WebKit/public/platform/WebString.h" |
| 11 | 11 |
| 12 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 12 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
| 13 | 13 |
| 14 // Death tests are not always available. When they are, they use NDEBUG for | 14 // Death tests are not always available, including on Android. |
| 15 // the DCHECK variant, which is not sufficient when defined(DCHECK_ALWAYS_ON). | 15 // EXPECT_DEBUG_DEATH_PORTABLE executes tests correctly except in the case that |
| 16 // EXPECT_DCHECK_DEATH handles all these cases. The test will execute correctly | 16 // death tests are not available and NDEBUG is not defined. |
| 17 // except in the case that death tests are not available but DCHECKs are on. | |
| 18 #if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) | 17 #if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) |
| 19 #if defined(DCHECK_ALWAYS_ON) | 18 #define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \ |
| 20 #define EXPECT_DCHECK_DEATH(statement, regex) \ | 19 EXPECT_DEBUG_DEATH(statement, regex) |
| 21 EXPECT_DEATH(statement, regex) | |
| 22 #else | 20 #else |
| 23 #define EXPECT_DCHECK_DEATH(statement, regex) \ | 21 #if defined(NDEBUG) |
| 24 EXPECT_DEBUG_DEATH(statement, regex) | 22 #define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \ |
| 25 #endif // defined(DCHECK_ALWAYS_ON) | |
| 26 #else // defined(GTEST_HAS_DEATH_TEST) | |
| 27 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) | |
| 28 #define EXPECT_DCHECK_DEATH(statement, regex) \ | |
| 29 do { statement; } while (false) | 23 do { statement; } while (false) |
| 30 #else | 24 #else |
| 31 #include "base/logging.h" | 25 #include "base/logging.h" |
| 32 #define EXPECT_DCHECK_DEATH(statement, regex) \ | 26 #define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \ |
| 33 LOG(WARNING) << "Death tests are not supported on this platform.\n" \ | 27 LOG(WARNING) << "Death tests are not supported on this platform.\n" \ |
| 34 << "Statement '" #statement "' cannot be verified."; | 28 << "Statement '" #statement "' cannot be verified."; |
| 35 #endif // defined(NDEBUG) && defined(DCHECK_ALWAYS_ON) | 29 #endif // defined(NDEBUG) |
| 36 #endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) | 30 #endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) |
| 37 | 31 |
| 38 #if defined(WIDEVINE_CDM_AVAILABLE) && \ | 32 #if defined(WIDEVINE_CDM_AVAILABLE) && \ |
| 39 defined(OS_LINUX) && !defined(OS_CHROMEOS) | 33 defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 40 #include <gnu/libc-version.h> | 34 #include <gnu/libc-version.h> |
| 41 #endif | 35 #endif |
| 42 | 36 |
| 43 using WebKit::WebString; | 37 using WebKit::WebString; |
| 44 | 38 |
| 45 #if defined(USE_PROPRIETARY_CODECS) | 39 #if defined(USE_PROPRIETARY_CODECS) |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 // Not yet out from behind the vendor prefix. | 195 // Not yet out from behind the vendor prefix. |
| 202 EXPECT_FALSE(IsConcreteSupportedKeySystem("org.w3.clearkey")); | 196 EXPECT_FALSE(IsConcreteSupportedKeySystem("org.w3.clearkey")); |
| 203 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( | 197 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( |
| 204 "video/webm", no_codecs(), "org.w3.clearkey")); | 198 "video/webm", no_codecs(), "org.w3.clearkey")); |
| 205 | 199 |
| 206 EXPECT_STREQ("ClearKey", | 200 EXPECT_STREQ("ClearKey", |
| 207 KeySystemNameForUMA(WebString::fromUTF8(kClearKey)).c_str()); | 201 KeySystemNameForUMA(WebString::fromUTF8(kClearKey)).c_str()); |
| 208 | 202 |
| 209 EXPECT_TRUE(CanUseAesDecryptor(kClearKey)); | 203 EXPECT_TRUE(CanUseAesDecryptor(kClearKey)); |
| 210 #if defined(ENABLE_PEPPER_CDMS) | 204 #if defined(ENABLE_PEPPER_CDMS) |
| 211 EXPECT_TRUE(GetPepperType(kClearKey).empty()); // Does not use Pepper. | 205 std::string type; |
| 206 EXPECT_DEBUG_DEATH(type = GetPepperType(kClearKey), |
| 207 "webkit-org.w3.clearkey is not Pepper-based"); |
| 208 EXPECT_TRUE(type.empty()); |
| 212 #endif | 209 #endif |
| 213 } | 210 } |
| 214 | 211 |
| 215 TEST_F(KeySystemsTest, ClearKey_Parent) { | 212 TEST_F(KeySystemsTest, ClearKey_Parent) { |
| 216 const char* const kClearKeyParent = "webkit-org.w3"; | 213 const char* const kClearKeyParent = "webkit-org.w3"; |
| 217 | 214 |
| 218 // The parent should be supported but is not. See http://crbug.com/164303. | 215 // The parent should be supported but is not. See http://crbug.com/164303. |
| 219 EXPECT_FALSE( | 216 EXPECT_FALSE( |
| 220 IsConcreteSupportedKeySystem(WebString::fromUTF8(kClearKeyParent))); | 217 IsConcreteSupportedKeySystem(WebString::fromUTF8(kClearKeyParent))); |
| 221 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( | 218 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( |
| 222 "video/webm", no_codecs(), kClearKeyParent)); | 219 "video/webm", no_codecs(), kClearKeyParent)); |
| 223 | 220 |
| 224 // The parent is not supported for most things. | 221 // The parent is not supported for most things. |
| 225 EXPECT_STREQ("Unknown", | 222 EXPECT_STREQ("Unknown", |
| 226 KeySystemNameForUMA(WebString::fromUTF8(kClearKeyParent)).c_str()); | 223 KeySystemNameForUMA(WebString::fromUTF8(kClearKeyParent)).c_str()); |
| 227 EXPECT_FALSE(CanUseAesDecryptor(kClearKeyParent)); | 224 bool result = false; |
| 225 EXPECT_DEBUG_DEATH_PORTABLE(result = CanUseAesDecryptor(kClearKeyParent), |
| 226 "webkit-org.w3 is not a known concrete system"); |
| 227 EXPECT_FALSE(result); |
| 228 #if defined(ENABLE_PEPPER_CDMS) | 228 #if defined(ENABLE_PEPPER_CDMS) |
| 229 std::string type; | 229 std::string type; |
| 230 EXPECT_DCHECK_DEATH(type = GetPepperType(kClearKeyParent), | 230 EXPECT_DEBUG_DEATH(type = GetPepperType(kClearKeyParent), |
| 231 "webkit-org.w3 is not a concrete system"); | 231 "webkit-org.w3 is not a known concrete system"); |
| 232 EXPECT_TRUE(type.empty()); | 232 EXPECT_TRUE(type.empty()); |
| 233 #endif | 233 #endif |
| 234 } | 234 } |
| 235 | 235 |
| 236 TEST_F(KeySystemsTest, ClearKey_IsSupportedKeySystem_InvalidVariants) { | 236 TEST_F(KeySystemsTest, ClearKey_IsSupportedKeySystem_InvalidVariants) { |
| 237 // Case sensitive. | 237 // Case sensitive. |
| 238 EXPECT_FALSE(IsConcreteSupportedKeySystem("webkit-org.w3.ClEaRkEy")); | 238 EXPECT_FALSE(IsConcreteSupportedKeySystem("webkit-org.w3.ClEaRkEy")); |
| 239 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( | 239 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( |
| 240 "video/webm", no_codecs(), "webkit-org.w3.ClEaRkEy")); | 240 "video/webm", no_codecs(), "webkit-org.w3.ClEaRkEy")); |
| 241 | 241 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 EXPECT_ECK( | 386 EXPECT_ECK( |
| 387 IsConcreteSupportedKeySystem(WebString::fromUTF8(kExternalClearKey))); | 387 IsConcreteSupportedKeySystem(WebString::fromUTF8(kExternalClearKey))); |
| 388 EXPECT_ECK(IsSupportedKeySystemWithMediaMimeType( | 388 EXPECT_ECK(IsSupportedKeySystemWithMediaMimeType( |
| 389 "video/webm", no_codecs(), kExternalClearKey)); | 389 "video/webm", no_codecs(), kExternalClearKey)); |
| 390 | 390 |
| 391 // External Clear Key does not have a UMA name because it is for testing. | 391 // External Clear Key does not have a UMA name because it is for testing. |
| 392 EXPECT_STREQ( | 392 EXPECT_STREQ( |
| 393 "Unknown", | 393 "Unknown", |
| 394 KeySystemNameForUMA(WebString::fromUTF8(kExternalClearKey)).c_str()); | 394 KeySystemNameForUMA(WebString::fromUTF8(kExternalClearKey)).c_str()); |
| 395 | 395 |
| 396 #if defined(ENABLE_PEPPER_CDMS) |
| 396 EXPECT_FALSE(CanUseAesDecryptor(kExternalClearKey)); | 397 EXPECT_FALSE(CanUseAesDecryptor(kExternalClearKey)); |
| 397 #if defined(ENABLE_PEPPER_CDMS) | |
| 398 EXPECT_STREQ("application/x-ppapi-clearkey-cdm", | 398 EXPECT_STREQ("application/x-ppapi-clearkey-cdm", |
| 399 GetPepperType(kExternalClearKey).c_str()); | 399 GetPepperType(kExternalClearKey).c_str()); |
| 400 #else |
| 401 bool result = false; |
| 402 EXPECT_DEBUG_DEATH_PORTABLE( |
| 403 result = CanUseAesDecryptor(kExternalClearKey), |
| 404 "org.chromium.externalclearkey is not a known concrete system"); |
| 405 EXPECT_FALSE(result); |
| 400 #endif | 406 #endif |
| 401 } | 407 } |
| 402 | 408 |
| 403 TEST_F(KeySystemsTest, ExternalClearKey_Parent) { | 409 TEST_F(KeySystemsTest, ExternalClearKey_Parent) { |
| 404 const char* const kExternalClearKeyParent = "org.chromium"; | 410 const char* const kExternalClearKeyParent = "org.chromium"; |
| 405 | 411 |
| 406 // The parent should be supported but is not. See http://crbug.com/164303. | 412 // The parent should be supported but is not. See http://crbug.com/164303. |
| 407 EXPECT_FALSE(IsConcreteSupportedKeySystem( | 413 EXPECT_FALSE(IsConcreteSupportedKeySystem( |
| 408 WebString::fromUTF8(kExternalClearKeyParent))); | 414 WebString::fromUTF8(kExternalClearKeyParent))); |
| 409 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( | 415 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( |
| 410 "video/webm", no_codecs(), kExternalClearKeyParent)); | 416 "video/webm", no_codecs(), kExternalClearKeyParent)); |
| 411 | 417 |
| 412 // The parent is not supported for most things. | 418 // The parent is not supported for most things. |
| 413 EXPECT_STREQ("Unknown", | 419 EXPECT_STREQ("Unknown", |
| 414 KeySystemNameForUMA( | 420 KeySystemNameForUMA( |
| 415 WebString::fromUTF8(kExternalClearKeyParent)).c_str()); | 421 WebString::fromUTF8(kExternalClearKeyParent)).c_str()); |
| 416 EXPECT_FALSE(CanUseAesDecryptor(kExternalClearKeyParent)); | 422 bool result = false; |
| 423 EXPECT_DEBUG_DEATH_PORTABLE( |
| 424 result = CanUseAesDecryptor(kExternalClearKeyParent), |
| 425 "org.chromium is not a known concrete system"); |
| 426 EXPECT_FALSE(result); |
| 417 #if defined(ENABLE_PEPPER_CDMS) | 427 #if defined(ENABLE_PEPPER_CDMS) |
| 418 std::string type; | 428 std::string type; |
| 419 EXPECT_DCHECK_DEATH(type = GetPepperType(kExternalClearKeyParent), | 429 EXPECT_DEBUG_DEATH(type = GetPepperType(kExternalClearKeyParent), |
| 420 "org.chromium is not a concrete system"); | 430 "org.chromium is not a known concrete system"); |
| 421 EXPECT_TRUE(type.empty()); | 431 EXPECT_TRUE(type.empty()); |
| 422 #endif | 432 #endif |
| 423 } | 433 } |
| 424 | 434 |
| 425 TEST_F(KeySystemsTest, ExternalClearKey_IsSupportedKeySystem_InvalidVariants) { | 435 TEST_F(KeySystemsTest, ExternalClearKey_IsSupportedKeySystem_InvalidVariants) { |
| 426 // Case sensitive. | 436 // Case sensitive. |
| 427 EXPECT_FALSE(IsConcreteSupportedKeySystem("org.chromium.ExTeRnAlClEaRkEy")); | 437 EXPECT_FALSE(IsConcreteSupportedKeySystem("org.chromium.ExTeRnAlClEaRkEy")); |
| 428 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( | 438 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( |
| 429 "video/webm", no_codecs(), | 439 "video/webm", no_codecs(), |
| 430 "org.chromium.ExTeRnAlClEaRkEy")); | 440 "org.chromium.ExTeRnAlClEaRkEy")); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 | 597 |
| 588 #if defined(WIDEVINE_CDM_AVAILABLE) | 598 #if defined(WIDEVINE_CDM_AVAILABLE) |
| 589 const char* const kWidevineUmaName = "Widevine"; | 599 const char* const kWidevineUmaName = "Widevine"; |
| 590 #else | 600 #else |
| 591 const char* const kWidevineUmaName = "Unknown"; | 601 const char* const kWidevineUmaName = "Unknown"; |
| 592 #endif | 602 #endif |
| 593 EXPECT_STREQ( | 603 EXPECT_STREQ( |
| 594 kWidevineUmaName, | 604 kWidevineUmaName, |
| 595 KeySystemNameForUMA(WebString::fromUTF8(kWidevineAlpha)).c_str()); | 605 KeySystemNameForUMA(WebString::fromUTF8(kWidevineAlpha)).c_str()); |
| 596 | 606 |
| 607 #if defined(WIDEVINE_CDM_AVAILABLE) |
| 597 EXPECT_FALSE(CanUseAesDecryptor(kWidevineAlpha)); | 608 EXPECT_FALSE(CanUseAesDecryptor(kWidevineAlpha)); |
| 609 #else |
| 610 bool result = false; |
| 611 EXPECT_DEBUG_DEATH_PORTABLE( |
| 612 result = CanUseAesDecryptor(kWidevineAlpha), |
| 613 "com.widevine.alpha is not a known concrete system"); |
| 614 EXPECT_FALSE(result); |
| 615 #endif // defined(WIDEVINE_CDM_AVAILABLE) |
| 616 |
| 598 #if defined(ENABLE_PEPPER_CDMS) | 617 #if defined(ENABLE_PEPPER_CDMS) |
| 599 #if defined(WIDEVINE_CDM_AVAILABLE) | 618 #if defined(WIDEVINE_CDM_AVAILABLE) |
| 600 EXPECT_STREQ("application/x-ppapi-widevine-cdm", | 619 EXPECT_STREQ("application/x-ppapi-widevine-cdm", |
| 601 GetPepperType(kWidevineAlpha).c_str()); | 620 GetPepperType(kWidevineAlpha).c_str()); |
| 602 #else | 621 #else |
| 603 std::string type; | 622 std::string type; |
| 604 EXPECT_DCHECK_DEATH(type = GetPepperType(kWidevineAlpha), | 623 EXPECT_DEBUG_DEATH(type = GetPepperType(kWidevineAlpha), |
| 605 "com.widevine.alpha is not a concrete system"); | 624 "com.widevine.alpha is not a known concrete system"); |
| 606 EXPECT_TRUE(type.empty()); | 625 EXPECT_TRUE(type.empty()); |
| 607 #endif // defined(WIDEVINE_CDM_AVAILABLE) | 626 #endif // defined(WIDEVINE_CDM_AVAILABLE) |
| 608 #endif // defined(ENABLE_PEPPER_CDMS) | 627 #endif // defined(ENABLE_PEPPER_CDMS) |
| 609 | 628 |
| 610 } | 629 } |
| 611 | 630 |
| 612 TEST_F(KeySystemsTest, Widevine_Parent) { | 631 TEST_F(KeySystemsTest, Widevine_Parent) { |
| 613 // The parent system is not a concrete system but is supported. | 632 // The parent system is not a concrete system but is supported. |
| 614 EXPECT_FALSE(IsConcreteSupportedKeySystem(WebString::fromUTF8(kWidevine))); | 633 EXPECT_FALSE(IsConcreteSupportedKeySystem(WebString::fromUTF8(kWidevine))); |
| 615 EXPECT_WV(IsSupportedKeySystemWithMediaMimeType( | 634 EXPECT_WV(IsSupportedKeySystemWithMediaMimeType( |
| 616 "video/webm", no_codecs(), kWidevine)); | 635 "video/webm", no_codecs(), kWidevine)); |
| 617 | 636 |
| 618 // The parent is not supported for most things. | 637 // The parent is not supported for most things. |
| 619 EXPECT_STREQ("Unknown", | 638 EXPECT_STREQ("Unknown", |
| 620 KeySystemNameForUMA(WebString::fromUTF8(kWidevine)).c_str()); | 639 KeySystemNameForUMA(WebString::fromUTF8(kWidevine)).c_str()); |
| 621 EXPECT_FALSE(CanUseAesDecryptor(kWidevine)); | 640 bool result = false; |
| 641 EXPECT_DEBUG_DEATH_PORTABLE(result = CanUseAesDecryptor(kWidevine), |
| 642 "com.widevine is not a known concrete system"); |
| 643 EXPECT_FALSE(result); |
| 622 #if defined(ENABLE_PEPPER_CDMS) | 644 #if defined(ENABLE_PEPPER_CDMS) |
| 623 std::string type; | 645 std::string type; |
| 624 EXPECT_DCHECK_DEATH(type = GetPepperType(kWidevine), | 646 EXPECT_DEBUG_DEATH(type = GetPepperType(kWidevine), |
| 625 "com.widevine is not a concrete system"); | 647 "com.widevine is not a known concrete system"); |
| 626 EXPECT_TRUE(type.empty()); | 648 EXPECT_TRUE(type.empty()); |
| 627 #endif | 649 #endif |
| 628 } | 650 } |
| 629 | 651 |
| 630 TEST_F(KeySystemsTest, Widevine_IsSupportedKeySystem_InvalidVariants) { | 652 TEST_F(KeySystemsTest, Widevine_IsSupportedKeySystem_InvalidVariants) { |
| 631 // Case sensitive. | 653 // Case sensitive. |
| 632 EXPECT_FALSE(IsConcreteSupportedKeySystem("com.widevine.AlPhA")); | 654 EXPECT_FALSE(IsConcreteSupportedKeySystem("com.widevine.AlPhA")); |
| 633 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( | 655 EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( |
| 634 "video/webm", no_codecs(), "com.widevine.AlPhA")); | 656 "video/webm", no_codecs(), "com.widevine.AlPhA")); |
| 635 | 657 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 } | 817 } |
| 796 | 818 |
| 797 #if defined(OS_ANDROID) | 819 #if defined(OS_ANDROID) |
| 798 TEST_F(KeySystemsTest, GetUUID_Widevine) { | 820 TEST_F(KeySystemsTest, GetUUID_Widevine) { |
| 799 #if defined(WIDEVINE_CDM_AVAILABLE) | 821 #if defined(WIDEVINE_CDM_AVAILABLE) |
| 800 std::vector<uint8> uuid = GetUUID(kWidevineAlpha); | 822 std::vector<uint8> uuid = GetUUID(kWidevineAlpha); |
| 801 EXPECT_EQ(16u, uuid.size()); | 823 EXPECT_EQ(16u, uuid.size()); |
| 802 EXPECT_EQ(0xED, uuid[15]); | 824 EXPECT_EQ(0xED, uuid[15]); |
| 803 #else | 825 #else |
| 804 std::vector<uint8> uuid; | 826 std::vector<uint8> uuid; |
| 805 EXPECT_DCHECK_DEATH(uuid = GetUUID(kWidevineAlpha), | 827 EXPECT_DEBUG_DEATH_PORTABLE( |
| 806 "com.widevine.alpha is not a concrete system"); | 828 uuid = GetUUID(kWidevineAlpha), |
| 829 "com.widevine.alpha is not a known concrete system"); |
| 807 EXPECT_TRUE(uuid.empty()); | 830 EXPECT_TRUE(uuid.empty()); |
| 808 #endif | 831 #endif |
| 809 } | 832 } |
| 810 | 833 |
| 811 TEST_F(KeySystemsTest, GetUUID_Unrecognized) { | 834 TEST_F(KeySystemsTest, GetUUID_Unrecognized) { |
| 812 std::vector<uint8> uuid; | 835 std::vector<uint8> uuid; |
| 813 EXPECT_DCHECK_DEATH(uuid = GetUUID(kWidevine), | 836 EXPECT_DEBUG_DEATH_PORTABLE(uuid = GetUUID(kWidevine), |
| 814 "com.widevine is not a concrete system"); | 837 "com.widevine is not a known concrete system"); |
| 815 EXPECT_TRUE(uuid.empty()); | 838 EXPECT_TRUE(uuid.empty()); |
| 816 | 839 |
| 817 EXPECT_TRUE(GetUUID(kClearKey).empty()); | 840 EXPECT_TRUE(GetUUID(kClearKey).empty()); |
| 818 | 841 |
| 819 EXPECT_DCHECK_DEATH(uuid = GetUUID(""), " is not a concrete system"); | 842 EXPECT_DEBUG_DEATH_PORTABLE(uuid = GetUUID(""), " is not a concrete system"); |
| 820 EXPECT_TRUE(uuid.empty()); | 843 EXPECT_TRUE(uuid.empty()); |
| 821 } | 844 } |
| 822 #endif // defined(OS_ANDROID) | 845 #endif // defined(OS_ANDROID) |
| 823 | 846 |
| 824 } // namespace content | 847 } // namespace content |
| OLD | NEW |