Commit 36329152 authored by ddorwin@chromium.org's avatar ddorwin@chromium.org

Explicitly register each key system.

Key systems are now explicitly added rather than loaded from arrays of structs.

This is in preparation for moving knowledge of key systems and registration out
of content/.

BUG=224793
TEST=exsting content_unittests

Review URL: https://chromiumcodereview.appspot.com/23464005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@220664 0039d316-1c4b-4281-b951-d872f2087c98
parent 2a9fa873
......@@ -32,6 +32,32 @@ class WebString;
namespace content {
// Adds a concrete key system along with platform-specific information about how
// to instantiate it. Must be called before AddSupportedType().
// May only be called once per |concrete_key_system|.
// When not empty, |parent_key_system| will add a mapping to the
// |concrete_key_system| that can be used to check supported types.
// Only one parent key system is currently supported per concrete key system.
CONTENT_EXPORT void AddConcreteSupportedKeySystem(
const std::string& concrete_key_system,
bool use_aes_decryptor,
#if defined(ENABLE_PEPPER_CDMS)
const std::string& pepper_type,
#elif defined(OS_ANDROID)
const uint8 uuid[16],
#endif
const std::string& parent_key_system);
// Specifies the container and codec combinations supported by
// |concrete_key_system|.
// Multiple codecs can be listed. In all cases, the container
// without a codec is also supported.
// |concrete_key_system| must be a concrete supported key system previously
// added using AddConcreteSupportedKeySystem().
CONTENT_EXPORT void AddSupportedType(const std::string& concrete_key_system,
const std::string& mime_type,
const std::string& codecs_list);
// Returns whether |key_system| is a real supported key system that can be
// instantiated.
// Abstract parent |key_system| strings will return false.
......@@ -51,17 +77,15 @@ CONTENT_EXPORT bool IsSupportedKeySystemWithMediaMimeType(
CONTENT_EXPORT std::string KeySystemNameForUMA(
const WebKit::WebString& key_system);
// Returns whether AesDecryptor can be used for the given |key_system|.
CONTENT_EXPORT bool CanUseAesDecryptor(const std::string& key_system);
// Returns whether AesDecryptor can be used for the given |concrete_key_system|.
CONTENT_EXPORT bool CanUseAesDecryptor(const std::string& concrete_key_system);
#if defined(ENABLE_PEPPER_CDMS)
// Returns the Pepper MIME type for |concrete_key_system|.
// Returns empty string if |concrete_key_system| is unknown or not Pepper-based.
CONTENT_EXPORT std::string GetPepperType(
const std::string& concrete_key_system);
#endif
#if defined(OS_ANDROID)
#elif defined(OS_ANDROID)
// Convert |concrete_key_system| to 16-byte Android UUID.
CONTENT_EXPORT std::vector<uint8> GetUUID(
const std::string& concrete_key_system);
......
......@@ -5,6 +5,7 @@
#include "content/renderer/media/crypto/key_systems_info.h"
#include "base/logging.h"
#include "content/renderer/media/crypto/key_systems.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
......@@ -30,11 +31,13 @@ static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
#if defined(ENABLE_PEPPER_CDMS)
static const char kExternalClearKeyKeySystem[] =
"org.chromium.externalclearkey";
#endif // defined(ENABLE_PEPPER_CDMS)
#elif defined(OS_ANDROID)
static const uint8 kEmptyUuid[16] =
{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
#endif
#if defined(WIDEVINE_CDM_AVAILABLE)
// TODO(ddorwin): Automatically support parent systems: http://crbug.com/164303.
static const char kWidevineBaseKeySystem[] = "com.widevine";
#if defined(WIDEVINE_CDM_CENC_SUPPORT_AVAILABLE)
// The supported codecs depend on what the CDM provides.
......@@ -56,108 +59,87 @@ static const char kWidevineAudioMp4Codecs[] =
#endif
#endif // defined(WIDEVINE_CDM_CENC_SUPPORT_AVAILABLE)
static inline bool IsWidevine(const std::string& key_system) {
return key_system == kWidevineKeySystem ||
key_system == kWidevineBaseKeySystem;
static void RegisterWidevine() {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
Version glibc_version(gnu_get_libc_version());
DCHECK(glibc_version.IsValid());
if (glibc_version.IsOlderThan(WIDEVINE_CDM_MIN_GLIBC_VERSION))
return;
#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
AddConcreteSupportedKeySystem(
kWidevineKeySystem,
false,
#if defined(ENABLE_PEPPER_CDMS)
kWidevineCdmPluginMimeType,
#elif defined(OS_ANDROID)
{ 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED },
#endif // defined(ENABLE_PEPPER_CDMS)
"com.widevine");
AddSupportedType(kWidevineKeySystem, "video/webm", "vorbis,vp8,vp8.0");
AddSupportedType(kWidevineKeySystem, "audio/webm", "vorbis");
#if defined(USE_PROPRIETARY_CODECS) && \
defined(WIDEVINE_CDM_CENC_SUPPORT_AVAILABLE)
AddSupportedType(kWidevineKeySystem, "video/mp4", kWidevineVideoMp4Codecs);
AddSupportedType(kWidevineKeySystem, "audio/mp4", kWidevineAudioMp4Codecs);
#endif // defined(USE_PROPRIETARY_CODECS) &&
// defined(WIDEVINE_CDM_CENC_SUPPORT_AVAILABLE)
}
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#endif // WIDEVINE_CDM_AVAILABLE
const MediaFormatAndKeySystem kSupportedFormatKeySystemCombinations[] = {
static void RegisterClearKey() {
// Clear Key.
{ "video/webm", "vorbis,vp8,vp8.0", kClearKeyKeySystem },
{ "audio/webm", "vorbis", kClearKeyKeySystem },
AddConcreteSupportedKeySystem(
kClearKeyKeySystem,
true,
#if defined(ENABLE_PEPPER_CDMS)
std::string(),
#elif defined(OS_ANDROID)
kEmptyUuid,
#endif // defined(ENABLE_PEPPER_CDMS)
std::string());
AddSupportedType(kClearKeyKeySystem, "video/webm", "vorbis,vp8,vp8.0");
AddSupportedType(kClearKeyKeySystem, "audio/webm", "vorbis");
#if defined(USE_PROPRIETARY_CODECS)
{ "video/mp4", "avc1,mp4a", kClearKeyKeySystem },
{ "audio/mp4", "mp4a", kClearKeyKeySystem },
AddSupportedType(kClearKeyKeySystem, "video/mp4", "avc1,mp4a");
AddSupportedType(kClearKeyKeySystem, "audio/mp4", "mp4a");
#endif // defined(USE_PROPRIETARY_CODECS)
}
#if defined(ENABLE_PEPPER_CDMS)
static void RegisterExternalClearKey() {
// External Clear Key (used for testing).
{ "video/webm", "vorbis,vp8,vp8.0", kExternalClearKeyKeySystem },
{ "audio/webm", "vorbis", kExternalClearKeyKeySystem },
AddConcreteSupportedKeySystem(kExternalClearKeyKeySystem, false,
"application/x-ppapi-clearkey-cdm",
std::string());
AddSupportedType(kExternalClearKeyKeySystem,
"video/webm", "vorbis,vp8,vp8.0");
AddSupportedType(kExternalClearKeyKeySystem, "audio/webm", "vorbis");
#if defined(USE_PROPRIETARY_CODECS)
{ "video/mp4", "avc1,mp4a", kExternalClearKeyKeySystem },
{ "audio/mp4", "mp4a", kExternalClearKeyKeySystem },
AddSupportedType(kExternalClearKeyKeySystem, "video/mp4", "avc1,mp4a");
AddSupportedType(kExternalClearKeyKeySystem, "audio/mp4", "mp4a");
#endif // defined(USE_PROPRIETARY_CODECS)
}
#endif // defined(ENABLE_PEPPER_CDMS)
#if defined(WIDEVINE_CDM_AVAILABLE)
// Widevine.
{ "video/webm", "vorbis,vp8,vp8.0", kWidevineKeySystem },
{ "audio/webm", "vorbis", kWidevineKeySystem },
#if defined(USE_PROPRIETARY_CODECS)
#if defined(WIDEVINE_CDM_CENC_SUPPORT_AVAILABLE)
{ "video/mp4", kWidevineVideoMp4Codecs, kWidevineKeySystem },
{ "audio/mp4", kWidevineAudioMp4Codecs, kWidevineKeySystem },
#endif // defined(WIDEVINE_CDM_CENC_SUPPORT_AVAILABLE)
#endif // defined(USE_PROPRIETARY_CODECS)
#endif // WIDEVINE_CDM_AVAILABLE
};
const int kNumSupportedFormatKeySystemCombinations =
arraysize(kSupportedFormatKeySystemCombinations);
void RegisterKeySystems() {
RegisterClearKey();
#if defined(ENABLE_PEPPER_CDMS)
const KeySystemPepperTypePair kKeySystemToPepperTypeMapping[] = {
{ kExternalClearKeyKeySystem, "application/x-ppapi-clearkey-cdm"},
#if defined(WIDEVINE_CDM_AVAILABLE)
{ kWidevineKeySystem, kWidevineCdmPluginMimeType}
#endif // WIDEVINE_CDM_AVAILABLE
};
const int kNumKeySystemToPepperTypeMapping =
arraysize(kKeySystemToPepperTypeMapping);
#endif // defined(ENABLE_PEPPER_CDMS)
#if defined(OS_ANDROID)
// TODO(qinmin): add UUIDs for other key systems.
const KeySystemUUIDPair kKeySystemToUUIDMapping[] = {
#if defined(WIDEVINE_CDM_AVAILABLE)
{ kWidevineKeySystem, { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }
}
#endif // defined(WIDEVINE_CDM_AVAILABLE)
};
// arraySize() does not work if the array is empty, so use ARRAYSIZE_UNSAFE().
const int kNumKeySystemToUUIDMapping =
ARRAYSIZE_UNSAFE(kKeySystemToUUIDMapping);
#endif // defined(OS_ANDROID)
bool IsOSIncompatible(const std::string& concrete_key_system) {
DCHECK(IsConcreteKeySystem(concrete_key_system))
<< concrete_key_system << " is not a concrete system";
#if defined(WIDEVINE_CDM_AVAILABLE) && \
defined(OS_LINUX) && !defined(OS_CHROMEOS)
if (IsWidevine(concrete_key_system)) {
Version glibc_version(gnu_get_libc_version());
DCHECK(glibc_version.IsValid());
return glibc_version.IsOlderThan(WIDEVINE_CDM_MIN_GLIBC_VERSION);
}
RegisterExternalClearKey();
#endif
return false;
}
std::string EnsureConcreteKeySystem(const std::string& key_system) {
#if defined(WIDEVINE_CDM_AVAILABLE)
if (key_system == kWidevineKeySystem || key_system == kWidevineBaseKeySystem)
return kWidevineKeySystem;
#endif // WIDEVINE_CDM_AVAILABLE
// No parent names for Clear Key.
if (key_system == kClearKeyKeySystem)
return kClearKeyKeySystem;
#if defined(ENABLE_PEPPER_CDMS)
// No parent names for External Clear Key.
if (key_system == kExternalClearKeyKeySystem)
return kExternalClearKeyKeySystem;
#endif // defined(ENABLE_PEPPER_CDMS)
return std::string();
RegisterWidevine();
#endif
}
bool IsCanPlayTypeSuppressed(const std::string& key_system) {
#if defined(DISABLE_WIDEVINE_CDM_CANPLAYTYPE)
// See http://crbug.com/237627.
if (IsWidevine(key_system) &&
if (key_system == kWidevineKeySystem &&
!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kOverrideEncryptedMediaCanPlayType))
return true;
......@@ -175,8 +157,4 @@ std::string KeySystemNameForUMAInternal(const WebKit::WebString& key_system) {
return "Unknown";
}
bool CanUseAesDecryptorInternal(const std::string& key_system) {
return key_system == kClearKeyKeySystem;
}
} // namespace content
......@@ -15,79 +15,18 @@ class WebString;
namespace content {
struct MediaFormatAndKeySystem {
const char* mime_type;
const char* codecs_list;
const char* key_system;
};
#if defined(ENABLE_PEPPER_CDMS)
struct KeySystemPepperTypePair {
const char* key_system;
const char* type;
};
#endif // defined(ENABLE_PEPPER_CDMS)
#if defined(OS_ANDROID)
struct KeySystemUUIDPair {
const char* key_system;
const uint8 uuid[16];
};
#endif // defined(OS_ANDROID)
// Specifies the container and codec combinations supported by individual
// key systems. Each line is a container-codecs combination and the key system
// that supports it. Multiple codecs can be listed. In all cases, the container
// without a codec is also supported.
// This list is converted at runtime into individual container-codec-key system
// entries in KeySystems::key_system_map_.
extern const MediaFormatAndKeySystem kSupportedFormatKeySystemCombinations[];
extern const int kNumSupportedFormatKeySystemCombinations;
#if defined(ENABLE_PEPPER_CDMS)
// There should be one entry for each key system.
extern const KeySystemPepperTypePair kKeySystemToPepperTypeMapping[];
extern const int kNumKeySystemToPepperTypeMapping;
#endif // defined(ENABLE_PEPPER_CDMS)
#if defined(OS_ANDROID)
// Mapping from key system to UUID, one entry per key system.
extern const KeySystemUUIDPair kKeySystemToUUIDMapping[];
extern const int kNumKeySystemToUUIDMapping;
#endif // defined(OS_ANDROID)
// Returns a concrete key system supported by the platform that most closely
// corresponds to |key_system|. The result can be passed to other functions that
// require a concrete key system.
// Returns null if a conversion cannot be made or |key_system| is unrecognized.
// The primary use case is to convert a parent key system to a concrete key
// system to check properties.
// If we ever have multiple children for a single parent, we may need a more
// complex solution that checks all concrete children until it gets true.
std::string EnsureConcreteKeySystem(const std::string& key_system);
// Returns whether |key_system| is a concrete key system.
// This is used for DCHECKs. Production code should use
// EnsureConcreteKeySystem().
inline bool IsConcreteKeySystem(const std::string& key_system) {
return !key_system.empty() &&
key_system == EnsureConcreteKeySystem(key_system);
}
// Returns true if there is a known incompatibility with the operating system.
bool IsOSIncompatible(const std::string& actual_key_system);
// TODO(ddorwin): Move registration to ContentClient.
void RegisterKeySystems();
// Returns true if canPlayType should return an empty string for |key_system|.
bool IsCanPlayTypeSuppressed(const std::string& key_system);
// Returns the name that UMA will use for the given |key_system|.
// This function can be called frequently. Hence this function should be
// implemented not to impact performance.
// implemented not to impact performance and does not rely on the main
// key system map.
std::string KeySystemNameForUMAInternal(const WebKit::WebString& key_system);
// Returns whether built-in AesDecryptor can be used for the given |key_system|.
bool CanUseAesDecryptorInternal(const std::string& key_system);
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_INFO_H_
......@@ -11,28 +11,22 @@
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
// Death tests are not always available. When they are, they use NDEBUG for
// the DCHECK variant, which is not sufficient when defined(DCHECK_ALWAYS_ON).
// EXPECT_DCHECK_DEATH handles all these cases. The test will execute correctly
// except in the case that death tests are not available but DCHECKs are on.
// Death tests are not always available, including on Android.
// EXPECT_DEBUG_DEATH_PORTABLE executes tests correctly except in the case that
// death tests are not available and NDEBUG is not defined.
#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
#if defined(DCHECK_ALWAYS_ON)
#define EXPECT_DCHECK_DEATH(statement, regex) \
EXPECT_DEATH(statement, regex)
#else
#define EXPECT_DCHECK_DEATH(statement, regex) \
#define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \
EXPECT_DEBUG_DEATH(statement, regex)
#endif // defined(DCHECK_ALWAYS_ON)
#else // defined(GTEST_HAS_DEATH_TEST)
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
#define EXPECT_DCHECK_DEATH(statement, regex) \
#else
#if defined(NDEBUG)
#define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \
do { statement; } while (false)
#else
#include "base/logging.h"
#define EXPECT_DCHECK_DEATH(statement, regex) \
#define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \
LOG(WARNING) << "Death tests are not supported on this platform.\n" \
<< "Statement '" #statement "' cannot be verified.";
#endif // defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
#endif // defined(NDEBUG)
#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
#if defined(WIDEVINE_CDM_AVAILABLE) && \
......@@ -208,7 +202,10 @@ TEST_F(KeySystemsTest, ClearKey_Basic) {
EXPECT_TRUE(CanUseAesDecryptor(kClearKey));
#if defined(ENABLE_PEPPER_CDMS)
EXPECT_TRUE(GetPepperType(kClearKey).empty()); // Does not use Pepper.
std::string type;
EXPECT_DEBUG_DEATH(type = GetPepperType(kClearKey),
"webkit-org.w3.clearkey is not Pepper-based");
EXPECT_TRUE(type.empty());
#endif
}
......@@ -224,11 +221,14 @@ TEST_F(KeySystemsTest, ClearKey_Parent) {
// The parent is not supported for most things.
EXPECT_STREQ("Unknown",
KeySystemNameForUMA(WebString::fromUTF8(kClearKeyParent)).c_str());
EXPECT_FALSE(CanUseAesDecryptor(kClearKeyParent));
bool result = false;
EXPECT_DEBUG_DEATH_PORTABLE(result = CanUseAesDecryptor(kClearKeyParent),
"webkit-org.w3 is not a known concrete system");
EXPECT_FALSE(result);
#if defined(ENABLE_PEPPER_CDMS)
std::string type;
EXPECT_DCHECK_DEATH(type = GetPepperType(kClearKeyParent),
"webkit-org.w3 is not a concrete system");
EXPECT_DEBUG_DEATH(type = GetPepperType(kClearKeyParent),
"webkit-org.w3 is not a known concrete system");
EXPECT_TRUE(type.empty());
#endif
}
......@@ -393,10 +393,16 @@ TEST_F(KeySystemsTest, ExternalClearKey_Basic) {
"Unknown",
KeySystemNameForUMA(WebString::fromUTF8(kExternalClearKey)).c_str());
EXPECT_FALSE(CanUseAesDecryptor(kExternalClearKey));
#if defined(ENABLE_PEPPER_CDMS)
EXPECT_FALSE(CanUseAesDecryptor(kExternalClearKey));
EXPECT_STREQ("application/x-ppapi-clearkey-cdm",
GetPepperType(kExternalClearKey).c_str());
#else
bool result = false;
EXPECT_DEBUG_DEATH_PORTABLE(
result = CanUseAesDecryptor(kExternalClearKey),
"org.chromium.externalclearkey is not a known concrete system");
EXPECT_FALSE(result);
#endif
}
......@@ -413,11 +419,15 @@ TEST_F(KeySystemsTest, ExternalClearKey_Parent) {
EXPECT_STREQ("Unknown",
KeySystemNameForUMA(
WebString::fromUTF8(kExternalClearKeyParent)).c_str());
EXPECT_FALSE(CanUseAesDecryptor(kExternalClearKeyParent));
bool result = false;
EXPECT_DEBUG_DEATH_PORTABLE(
result = CanUseAesDecryptor(kExternalClearKeyParent),
"org.chromium is not a known concrete system");
EXPECT_FALSE(result);
#if defined(ENABLE_PEPPER_CDMS)
std::string type;
EXPECT_DCHECK_DEATH(type = GetPepperType(kExternalClearKeyParent),
"org.chromium is not a concrete system");
EXPECT_DEBUG_DEATH(type = GetPepperType(kExternalClearKeyParent),
"org.chromium is not a known concrete system");
EXPECT_TRUE(type.empty());
#endif
}
......@@ -594,15 +604,24 @@ TEST_F(KeySystemsTest, Widevine_Basic) {
kWidevineUmaName,
KeySystemNameForUMA(WebString::fromUTF8(kWidevineAlpha)).c_str());
#if defined(WIDEVINE_CDM_AVAILABLE)
EXPECT_FALSE(CanUseAesDecryptor(kWidevineAlpha));
#else
bool result = false;
EXPECT_DEBUG_DEATH_PORTABLE(
result = CanUseAesDecryptor(kWidevineAlpha),
"com.widevine.alpha is not a known concrete system");
EXPECT_FALSE(result);
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#if defined(ENABLE_PEPPER_CDMS)
#if defined(WIDEVINE_CDM_AVAILABLE)
EXPECT_STREQ("application/x-ppapi-widevine-cdm",
GetPepperType(kWidevineAlpha).c_str());
#else
std::string type;
EXPECT_DCHECK_DEATH(type = GetPepperType(kWidevineAlpha),
"com.widevine.alpha is not a concrete system");
EXPECT_DEBUG_DEATH(type = GetPepperType(kWidevineAlpha),
"com.widevine.alpha is not a known concrete system");
EXPECT_TRUE(type.empty());
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#endif // defined(ENABLE_PEPPER_CDMS)
......@@ -618,11 +637,14 @@ TEST_F(KeySystemsTest, Widevine_Parent) {
// The parent is not supported for most things.
EXPECT_STREQ("Unknown",
KeySystemNameForUMA(WebString::fromUTF8(kWidevine)).c_str());
EXPECT_FALSE(CanUseAesDecryptor(kWidevine));
bool result = false;
EXPECT_DEBUG_DEATH_PORTABLE(result = CanUseAesDecryptor(kWidevine),
"com.widevine is not a known concrete system");
EXPECT_FALSE(result);
#if defined(ENABLE_PEPPER_CDMS)
std::string type;
EXPECT_DCHECK_DEATH(type = GetPepperType(kWidevine),
"com.widevine is not a concrete system");
EXPECT_DEBUG_DEATH(type = GetPepperType(kWidevine),
"com.widevine is not a known concrete system");
EXPECT_TRUE(type.empty());
#endif
}
......@@ -802,21 +824,22 @@ TEST_F(KeySystemsTest, GetUUID_Widevine) {
EXPECT_EQ(0xED, uuid[15]);
#else
std::vector<uint8> uuid;
EXPECT_DCHECK_DEATH(uuid = GetUUID(kWidevineAlpha),
"com.widevine.alpha is not a concrete system");
EXPECT_DEBUG_DEATH_PORTABLE(
uuid = GetUUID(kWidevineAlpha),
"com.widevine.alpha is not a known concrete system");
EXPECT_TRUE(uuid.empty());
#endif
}
TEST_F(KeySystemsTest, GetUUID_Unrecognized) {
std::vector<uint8> uuid;
EXPECT_DCHECK_DEATH(uuid = GetUUID(kWidevine),
"com.widevine is not a concrete system");
EXPECT_DEBUG_DEATH_PORTABLE(uuid = GetUUID(kWidevine),
"com.widevine is not a known concrete system");
EXPECT_TRUE(uuid.empty());
EXPECT_TRUE(GetUUID(kClearKey).empty());
EXPECT_DCHECK_DEATH(uuid = GetUUID(""), " is not a concrete system");
EXPECT_DEBUG_DEATH_PORTABLE(uuid = GetUUID(""), " is not a concrete system");
EXPECT_TRUE(uuid.empty());
}
#endif // defined(OS_ANDROID)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment