Source release 17.1.0
This commit is contained in:
50
cdm/cdm.gyp
50
cdm/cdm.gyp
@@ -1,5 +1,5 @@
|
||||
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine Master License
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
#
|
||||
# Refer to the distribution package's integration guide
|
||||
@@ -13,17 +13,16 @@
|
||||
'core.gypi',
|
||||
'util.gypi',
|
||||
], # Get list of core source files.
|
||||
'conditions': [
|
||||
['protobuf_config=="source"', {
|
||||
# Include protobuf targets used by protobuf_config=='source'
|
||||
'includes': ['../third_party/protobuf.gypi'],
|
||||
}],
|
||||
], # conditions
|
||||
'variables': {
|
||||
'has_dual_key%': 'false',
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'license_protocol',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'includes': ['../third_party/protoc.gypi'],
|
||||
'sources': [
|
||||
'../core/src/license_protocol.proto',
|
||||
@@ -33,9 +32,11 @@
|
||||
},
|
||||
},
|
||||
{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'device_files',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'includes': ['../third_party/protoc.gypi'],
|
||||
'sources': ['../core/src/device_files.proto',],
|
||||
'variables': {
|
||||
@@ -43,9 +44,11 @@
|
||||
},
|
||||
},
|
||||
{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'metrics_proto',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'includes': ['../third_party/protoc.gypi'],
|
||||
'sources': ['../metrics/src/wv_metrics.proto',],
|
||||
'variables': {
|
||||
@@ -53,17 +56,22 @@
|
||||
},
|
||||
},
|
||||
{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'widevine_utils',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'include_dirs': [
|
||||
'../util/include',
|
||||
],
|
||||
'sources': [ '<@(wvutil_sources)'],
|
||||
},
|
||||
{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'widevine_cdm_core',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'dependencies': [
|
||||
'device_files',
|
||||
'license_protocol',
|
||||
@@ -104,6 +112,16 @@
|
||||
'sources': [
|
||||
'../core/src/privacy_crypto_<(privacy_crypto_impl).cpp',
|
||||
],
|
||||
'conditions': [
|
||||
['privacy_crypto_impl=="apple"', {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/Security.framework',
|
||||
],
|
||||
},
|
||||
}],
|
||||
],
|
||||
}], # end else
|
||||
['oemcrypto_adapter_type=="dynamic"', {
|
||||
'sources': [
|
||||
@@ -112,14 +130,21 @@
|
||||
}],
|
||||
['oemcrypto_adapter_type=="static"', {
|
||||
'sources': [
|
||||
'../core/src/oemcrypto_adapter_static.cpp',
|
||||
'../core/src/oemcrypto_adapter_static.cpp',
|
||||
],
|
||||
}],
|
||||
# TODO(b/139814713): For testing and internal use only.
|
||||
['oemcrypto_adapter_type=="static_v15"', {
|
||||
['oemcrypto_adapter_type=="static_v16"', {
|
||||
'sources': [
|
||||
'../core/src/oemcrypto_adapter_static.cpp',
|
||||
'../core/src/oemcrypto_adapter_static_v16.cpp',
|
||||
'../core/src/oemcrypto_adapter_static_v17.cpp',
|
||||
],
|
||||
}],
|
||||
['has_dual_key=="true"', {
|
||||
'defines': ['HAS_DUAL_KEY'],
|
||||
}],
|
||||
['support_ota_keybox_functions=="false"', {
|
||||
'sources': [
|
||||
'../core/src/oemcrypto_ota_stubs.cpp',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -128,6 +153,7 @@
|
||||
# This is the widevine_ce_cdm built as a static library. This name does
|
||||
# not mean that it uses oemcrypto's static adapter. Control over which
|
||||
# adapter is used comes from the settings file for the platform.
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'widevine_ce_cdm_static',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
@@ -167,6 +193,7 @@
|
||||
],
|
||||
}, # widevine_cdm_static target
|
||||
{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'widevine_ce_cdm_shared',
|
||||
'type': 'shared_library',
|
||||
'dependencies': [
|
||||
@@ -179,6 +206,7 @@
|
||||
},
|
||||
},
|
||||
{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'dummy',
|
||||
'type': 'none',
|
||||
},
|
||||
|
||||
145
cdm/cdm_reboot_tests.gyp
Normal file
145
cdm/cdm_reboot_tests.gyp
Normal file
@@ -0,0 +1,145 @@
|
||||
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
#
|
||||
# Any top-level targets in this file (and their dependencies) will be built by
|
||||
# the CE CDM's ./build.py build system. Refer to the distribution package's
|
||||
# README for details.
|
||||
{
|
||||
'includes': [
|
||||
'platform_properties.gypi',
|
||||
],
|
||||
'variables': {
|
||||
# Directory where OEMCrypto header, test, and reference files lives.
|
||||
'oemcrypto_dir': '../oemcrypto',
|
||||
# Directory where widevine utilities live.
|
||||
'util_dir': '../util',
|
||||
'metrics_target': 'cdm.gyp:metrics_proto',
|
||||
'device_files_target': 'cdm.gyp:device_files',
|
||||
# The path to the test device cert source file.
|
||||
'device_cert_path%': 'test/device_cert.cpp',
|
||||
},
|
||||
'targets': [{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'widevine_ce_cdm_reboot_tests',
|
||||
'sources': [
|
||||
'test/cdm_reboot_test_main.cpp',
|
||||
'test/cdm_test_runner.cpp',
|
||||
'test/create_test_file_system.cpp',
|
||||
'<(device_cert_path)',
|
||||
'test/device_cert.h',
|
||||
'test/test_host.cpp',
|
||||
'test/test_host.h',
|
||||
'../core/test/config_test_env.cpp',
|
||||
'../core/test/fake_provisioning_server.cpp',
|
||||
'../core/test/http_socket.cpp',
|
||||
'../core/test/license_holder.cpp',
|
||||
'../core/test/license_request.cpp',
|
||||
'../core/test/reboot_test.cpp',
|
||||
'../core/test/test_base.cpp',
|
||||
'../core/test/test_printers.cpp',
|
||||
'../core/test/url_request.cpp',
|
||||
'../oemcrypto/test/oec_key_deriver.cpp',
|
||||
'../oemcrypto/test/oec_device_features.cpp',
|
||||
'../util/test/test_sleep.cpp',
|
||||
],
|
||||
'includes': [
|
||||
'../oemcrypto/odk/src/kdo.gypi',
|
||||
'../util/libssl_dependency.gypi',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../cdm/include',
|
||||
'../core/include',
|
||||
'../core/test',
|
||||
'../metrics/include',
|
||||
'../oemcrypto/test',
|
||||
'../oemcrypto/include',
|
||||
'../util/include',
|
||||
'../util/test',
|
||||
],
|
||||
'dependencies': [
|
||||
'cdm.gyp:widevine_ce_cdm_static',
|
||||
'../oemcrypto/odk/src/odk.gyp:odk',
|
||||
'../third_party/googletest.gyp:gmock',
|
||||
'../third_party/googletest.gyp:gtest',
|
||||
'<(metrics_target)',
|
||||
'<(device_files_target)',
|
||||
],
|
||||
'defines': [
|
||||
# The methods in util/ are marked as dllimport but in this case are
|
||||
# being loaded in the static library. So define this so Windows
|
||||
# doesn't look in a DLL for the implementations.
|
||||
'CORE_UTIL_IMPLEMENTATION',
|
||||
'UNIT_TEST',
|
||||
'CDM_TESTS',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCLinkerTool': {
|
||||
# Additionally, since they are loaded locally, suppress these
|
||||
# warnings.
|
||||
'AdditionalOptions': [
|
||||
'/IGNORE:4049',
|
||||
'/IGNORE:4217',
|
||||
],
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS=="ios"', {
|
||||
'type': 'loadable_module',
|
||||
'mac_xctest_bundle': '1',
|
||||
'defines': [
|
||||
'GTEST_FILTER="<(gtest_filter)"',
|
||||
],
|
||||
'dependencies': [
|
||||
'cdm_unittests.gyp:dummy_app',
|
||||
],
|
||||
'sources': [
|
||||
'test/gtest_xctest_wrapper.mm',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'BUNDLE_LOADER': '$(TEST_HOST)',
|
||||
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
|
||||
'WRAPPER_EXTENSION': 'xctest',
|
||||
},
|
||||
}, {
|
||||
'type': 'executable',
|
||||
}],
|
||||
['oemcrypto_lib=="ref"', {
|
||||
'dependencies': [
|
||||
'oemcrypto_reference_implementation.gyp:oec_ref',
|
||||
],
|
||||
}],
|
||||
# TODO(b/139814713): For testing and internal use only.
|
||||
['oemcrypto_adapter_type=="static_v15"', {
|
||||
'defines': [
|
||||
# This is used by the unit tests to use some v15 functions.
|
||||
'TEST_OEMCRYPTO_V15',
|
||||
],
|
||||
}],
|
||||
['oemcrypto_lib=="level3"', {
|
||||
'sources': [
|
||||
# The test impl of OEMCrypto_Level3FileSystem and its factory.
|
||||
'test/level3_file_system_ce_test.h',
|
||||
'test/level3_file_system_ce_test.cpp',
|
||||
'test/level3_file_system_ce_test_factory.cpp',
|
||||
],
|
||||
'conditions': [
|
||||
['oemcrypto_adapter_type=="dynamic" ', {
|
||||
'dependencies': [
|
||||
'../oemcrypto/level3/oec_level3.gyp:oec_level3_dynamic',
|
||||
],
|
||||
}, {
|
||||
'dependencies': [
|
||||
'../oemcrypto/level3/oec_level3.gyp:oec_level3_static',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['oemcrypto_lib=="target"', {
|
||||
'dependencies': [
|
||||
'<(oemcrypto_gyp_target)',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine Master License
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
#
|
||||
# Builds under the CDM ./build.py (target platform) build system
|
||||
# Refer to the distribution package's README for details.
|
||||
# Any top-level targets in this file (and their dependencies) will be built by
|
||||
# the CE CDM's ./build.py build system. Refer to the distribution package's
|
||||
# README for details.
|
||||
{
|
||||
'includes': [
|
||||
'platform_properties.gypi',
|
||||
@@ -15,103 +16,262 @@
|
||||
'util_dir': '../util',
|
||||
'metrics_target': 'cdm.gyp:metrics_proto',
|
||||
'device_files_target': 'cdm.gyp:device_files',
|
||||
# The path to the test device cert source file.
|
||||
'device_cert_path%': 'test/device_cert.cpp',
|
||||
# The path to the prebuilt CDM to test against. (iOS only)
|
||||
'prebuilt_cdm_path%': '',
|
||||
'prebuilt_cdm_cert%': '',
|
||||
'supports_dynamic_perf_test%': 0,
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'widevine_ce_cdm_unittest',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
# The test runner and the testing device certificate.
|
||||
'test/cdm_test_main.cpp',
|
||||
'test/device_cert.cpp',
|
||||
'test/device_cert.h',
|
||||
# The test host, which is required for all test suites on CE.
|
||||
'test/test_host.cpp',
|
||||
'test/test_host.h',
|
||||
'../util/test/test_sleep.cpp',
|
||||
],
|
||||
'includes': [
|
||||
'../oemcrypto/test/oemcrypto_unittests.gypi',
|
||||
'../oemcrypto/odk/src/kdo.gypi',
|
||||
'cdm_unittests.gypi',
|
||||
'core_unittests.gypi',
|
||||
'util_unittests.gypi',
|
||||
],
|
||||
'dependencies': [
|
||||
'cdm.gyp:widevine_ce_cdm_static',
|
||||
'../third_party/gmock.gyp:gmock',
|
||||
'../third_party/gmock.gyp:gtest',
|
||||
],
|
||||
'defines': [
|
||||
# The methods in util/ are marked as dllimport but in this case are
|
||||
# being loaded in the static library. So define this so Windows
|
||||
# doesn't look in a DLL for the implementations.
|
||||
'CORE_UTIL_IMPLEMENTATION',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCLinkerTool': {
|
||||
# Additionally, since they are loaded locally, suppress these
|
||||
# warnings.
|
||||
'AdditionalOptions': [
|
||||
'/IGNORE:4049',
|
||||
'/IGNORE:4217',
|
||||
],
|
||||
},
|
||||
'targets': [{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'widevine_ce_cdm_unittest',
|
||||
'sources': [
|
||||
'test/cdm_test_main.cpp',
|
||||
'test/cdm_test_runner.cpp',
|
||||
'test/create_test_file_system.cpp',
|
||||
'<(device_cert_path)',
|
||||
'test/device_cert.h',
|
||||
# The test host, which is required for all test suites on CE.
|
||||
'test/test_host.cpp',
|
||||
'test/test_host.h',
|
||||
'../util/test/test_sleep.cpp',
|
||||
],
|
||||
'includes': [
|
||||
'../oemcrypto/test/oemcrypto_unittests.gypi',
|
||||
'../oemcrypto/odk/src/kdo.gypi',
|
||||
'../oemcrypto/odk/test/odk_test.gypi',
|
||||
'../oemcrypto/util/oec_ref_util_unittests.gypi',
|
||||
'cdm_unittests.gypi',
|
||||
'core_unittests.gypi',
|
||||
'util_unittests.gypi',
|
||||
],
|
||||
'dependencies': [
|
||||
'cdm.gyp:widevine_ce_cdm_static',
|
||||
'../oemcrypto/util/oec_ref_util.gyp:oec_ref_util',
|
||||
'../third_party/googletest.gyp:gmock',
|
||||
'../third_party/googletest.gyp:gtest',
|
||||
],
|
||||
'defines': [
|
||||
# The methods in util/ are marked as dllimport but in this case are
|
||||
# being loaded in the static library. So define this so Windows
|
||||
# doesn't look in a DLL for the implementations.
|
||||
'CORE_UTIL_IMPLEMENTATION',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCLinkerTool': {
|
||||
# Additionally, since they are loaded locally, suppress these
|
||||
# warnings.
|
||||
'AdditionalOptions': [
|
||||
'/IGNORE:4049',
|
||||
'/IGNORE:4217',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['oemcrypto_lib=="ref"', {
|
||||
'dependencies': [
|
||||
'oec_ref',
|
||||
],
|
||||
}],
|
||||
# TODO(b/139814713): For testing and internal use only.
|
||||
['oemcrypto_adapter_type=="static_v15"', {
|
||||
'defines': [
|
||||
# This is used by the unit tests to use some v15 functions.
|
||||
'TEST_OEMCRYPTO_V15',
|
||||
],
|
||||
}],
|
||||
['oemcrypto_lib=="level3"', {
|
||||
'sources': [
|
||||
# The test impl of OEMCrypto_Level3FileSystem and its factory.
|
||||
'test/level3_file_system_ce_test.h',
|
||||
'test/level3_file_system_ce_test.cpp',
|
||||
'test/level3_file_system_ce_test_factory.cpp',
|
||||
],
|
||||
'conditions': [
|
||||
['oemcrypto_adapter_type=="dynamic" ', {
|
||||
'dependencies': [
|
||||
'../oemcrypto/level3/oec_level3.gyp:oec_level3_dynamic',
|
||||
],
|
||||
}, {
|
||||
'dependencies': [
|
||||
'../oemcrypto/level3/oec_level3.gyp:oec_level3_static',
|
||||
},
|
||||
'conditions': [
|
||||
['OS=="ios"', {
|
||||
'type': 'loadable_module',
|
||||
'mac_xctest_bundle': '1',
|
||||
'defines': [
|
||||
'GTEST_FILTER="<(gtest_filter)"',
|
||||
],
|
||||
'dependencies': [
|
||||
'dummy_app',
|
||||
],
|
||||
'sources': [
|
||||
'test/gtest_xctest_wrapper.mm',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'BUNDLE_LOADER': '$(TEST_HOST)',
|
||||
'INFOPLIST_FILE': 'test/info.plist',
|
||||
'PRODUCT_BUNDLE_IDENTIFIER': 'EQHXZ8M8AV.widevine_ce_cdm_unittest',
|
||||
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
|
||||
'WRAPPER_EXTENSION': 'xctest',
|
||||
},
|
||||
}, {
|
||||
'type': 'executable',
|
||||
}],
|
||||
['oemcrypto_lib=="ref"', {
|
||||
'dependencies': [
|
||||
'oemcrypto_reference_implementation.gyp:oec_ref',
|
||||
],
|
||||
}],
|
||||
# TODO(b/139814713): For testing and internal use only.
|
||||
['oemcrypto_adapter_type=="static_v15"', {
|
||||
'defines': [
|
||||
# This is used by the unit tests to use some v15 functions.
|
||||
'TEST_OEMCRYPTO_V15',
|
||||
],
|
||||
}],
|
||||
['oemcrypto_lib=="level3"', {
|
||||
'sources': [
|
||||
# The test impl of OEMCrypto_Level3FileSystem and its factory.
|
||||
'test/level3_file_system_ce_test.h',
|
||||
'test/level3_file_system_ce_test.cpp',
|
||||
'test/level3_file_system_ce_test_factory.cpp',
|
||||
],
|
||||
'conditions': [
|
||||
['oemcrypto_adapter_type=="dynamic" ', {
|
||||
'dependencies': [
|
||||
'../oemcrypto/level3/oec_level3.gyp:oec_level3_dynamic',
|
||||
],
|
||||
}, {
|
||||
'dependencies': [
|
||||
'../oemcrypto/level3/oec_level3.gyp:oec_level3_static',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['oemcrypto_lib=="target"', {
|
||||
'dependencies': [
|
||||
'<(oemcrypto_gyp_target)',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
'conditions': [
|
||||
['supports_dynamic_perf_test', {
|
||||
'targets': [{
|
||||
'target_name': 'widevine_perf_test_dynamic',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'<(device_cert_path)',
|
||||
'../core/test/config_test_env.cpp',
|
||||
'../core/test/http_socket.cpp',
|
||||
'../core/test/license_request.cpp',
|
||||
'../core/test/url_request.cpp',
|
||||
'../util/src/string_conversions.cpp',
|
||||
'../util/test/test_sleep.cpp',
|
||||
'src/log.cpp',
|
||||
'test/perf_test.cpp',
|
||||
'test/perf_test_dynamic.cpp',
|
||||
'test/test_host.cpp',
|
||||
],
|
||||
'includes': [ '../util/libssl_dependency.gypi' ],
|
||||
'include_dirs': [
|
||||
'../core/include',
|
||||
'../core/test',
|
||||
'../util/include',
|
||||
'../util/test',
|
||||
'include',
|
||||
],
|
||||
'dependencies': [
|
||||
'../third_party/googletest.gyp:gmock',
|
||||
'../third_party/googletest.gyp:gtest',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="linux"', {
|
||||
'libraries': [ '-ldl' ],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
}], # condition: supports_dynamic_perf_test
|
||||
['OS=="ios"', {
|
||||
'targets': [{
|
||||
'toolsets' : [ 'target' ],
|
||||
'target_name': 'dummy_app',
|
||||
'type': 'executable',
|
||||
'mac_bundle': '1',
|
||||
'sources': [
|
||||
'test/dummy_app.mm',
|
||||
],
|
||||
'libraries': [
|
||||
'CoreFoundation.framework',
|
||||
'UIKit.framework',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'INFOPLIST_FILE': 'test/info.plist',
|
||||
},
|
||||
'conditions': [
|
||||
['prebuilt_cdm_path!=""', {
|
||||
'copies': [{
|
||||
'destination': '<(PRODUCT_DIR)/dummy_app.app/Frameworks',
|
||||
'xcode_code_sign': 1,
|
||||
'files': [
|
||||
# GYP seems to always use relative paths here, even if they
|
||||
# start with '/'.
|
||||
'<!(realpath --relative-to=. "<(prebuilt_cdm_path)")',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['oemcrypto_lib=="target"', {
|
||||
'dependencies': [
|
||||
'<(oemcrypto_gyp_target)',
|
||||
],
|
||||
}],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
'conditions': [
|
||||
['supports_dynamic_perf_test', {
|
||||
'targets': [{
|
||||
'target_name': 'create_cert_cc',
|
||||
'type': 'none',
|
||||
'actions': [{
|
||||
'action_name': 'gen_cert',
|
||||
'message': 'Generating device_cert.cc',
|
||||
'msvs_cygwin_shell': 0,
|
||||
'inputs': [
|
||||
'create_cert_cc.py',
|
||||
'<(prebuilt_cdm_cert)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(INTERMEDIATE_DIR)/cert.cc',
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'create_cert_cc.py',
|
||||
'<(prebuilt_cdm_cert)',
|
||||
'<(INTERMEDIATE_DIR)/cert.cc',
|
||||
],
|
||||
}],
|
||||
}, {
|
||||
'target_name': 'widevine_perf_test_xctest',
|
||||
'type': 'loadable_module',
|
||||
'mac_xctest_bundle': '1',
|
||||
'defines': [
|
||||
'GTEST_FILTER="<(gtest_filter)"',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'BUNDLE_LOADER': '$(TEST_HOST)',
|
||||
'INFOPLIST_FILE': 'test/info.plist',
|
||||
'PRODUCT_BUNDLE_IDENTIFIER': 'EQHXZ8M8AV.widevine_perf_test_xctest',
|
||||
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
|
||||
'WRAPPER_EXTENSION': 'xctest',
|
||||
|
||||
'OTHER_LDFLAGS': [
|
||||
'-iframework',
|
||||
'<(prebuilt_cdm_path)/..',
|
||||
],
|
||||
},
|
||||
'libraries': [
|
||||
'<(prebuilt_cdm_path)',
|
||||
],
|
||||
'sources': [
|
||||
'<(INTERMEDIATE_DIR)/cert.cc',
|
||||
'../core/test/config_test_env.cpp',
|
||||
'../core/test/http_socket.cpp',
|
||||
'../core/test/license_request.cpp',
|
||||
'../core/test/url_request.cpp',
|
||||
'../util/src/string_conversions.cpp',
|
||||
'../util/test/test_clock.cpp',
|
||||
'../util/test/test_sleep.cpp',
|
||||
'src/log.cpp',
|
||||
'test/perf_test.cpp',
|
||||
'test/perf_test_xctest.mm',
|
||||
'test/test_host.cpp',
|
||||
],
|
||||
'includes': [ '../util/libssl_dependency.gypi' ],
|
||||
'include_dirs': [
|
||||
'../core/include',
|
||||
'../core/test',
|
||||
'../util/include',
|
||||
'../util/test',
|
||||
'include',
|
||||
],
|
||||
'dependencies': [
|
||||
'../third_party/googletest.gyp:gmock',
|
||||
'../third_party/googletest.gyp:gtest',
|
||||
'create_cert_cc',
|
||||
'dummy_app',
|
||||
],
|
||||
}],
|
||||
}], # condition: supports_dynamic_perf_test
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'oec_ref',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'includes': [
|
||||
'../oemcrypto/ref/oec_ref.gypi',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'oec_ref_shared',
|
||||
'type': 'shared_library',
|
||||
'dependencies': [
|
||||
'oec_ref'
|
||||
],
|
||||
},
|
||||
}], # condition: OS=="ios"
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
#source code may only be used and distributed under the Widevine Master License
|
||||
#source code may only be used and distributed under the Widevine License
|
||||
#Agreement.
|
||||
#
|
||||
# Include this in any custom unit test targets.
|
||||
@@ -21,6 +21,13 @@
|
||||
|
||||
'../util/test/test_sleep.cpp',
|
||||
],
|
||||
'conditions': [
|
||||
['support_ota_keybox_functions=="true"', {
|
||||
'sources': [
|
||||
'../core/test/keybox_ota_test.cpp',
|
||||
],
|
||||
}],
|
||||
],
|
||||
'include_dirs': [
|
||||
'../core/test',
|
||||
'../util/test',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
#source code may only be used and distributed under the Widevine Master License
|
||||
#source code may only be used and distributed under the Widevine License
|
||||
#Agreement.
|
||||
#
|
||||
# Include this in any custom unit test targets.
|
||||
@@ -19,6 +19,7 @@
|
||||
'../core/include/content_key_session.h',
|
||||
'../core/include/crypto_key.h',
|
||||
'../core/include/crypto_session.h',
|
||||
'../core/include/crypto_wrapped_key.h',
|
||||
'../core/include/device_files.h',
|
||||
'../core/include/entitlement_key_session.h',
|
||||
'../core/include/initialization_data.h',
|
||||
@@ -26,6 +27,9 @@
|
||||
'../core/include/license_key_status.h',
|
||||
'../core/include/license.h',
|
||||
'../core/include/oemcrypto_adapter.h',
|
||||
'../core/include/okp_fallback_policy.h',
|
||||
'../core/include/okp_info.h',
|
||||
'../core/include/ota_keybox_provisioner.h',
|
||||
'../core/include/policy_engine.h',
|
||||
'../core/include/policy_timers.h',
|
||||
'../core/include/policy_timers_v15.h',
|
||||
@@ -51,13 +55,18 @@
|
||||
'../core/src/initialization_data.cpp',
|
||||
'../core/src/license.cpp',
|
||||
'../core/src/license_key_status.cpp',
|
||||
'../core/src/okp_fallback_policy.cpp',
|
||||
'../core/src/okp_info.cpp',
|
||||
'../core/src/ota_keybox_provisioner.cpp',
|
||||
'../core/src/policy_engine.cpp',
|
||||
'../core/src/policy_timers.cpp',
|
||||
'../core/src/policy_timers_v15.cpp',
|
||||
'../core/src/policy_timers_v16.cpp',
|
||||
'../core/src/properties.cpp',
|
||||
'../core/src/service_certificate.cpp',
|
||||
'../core/src/system_id_extractor.cpp',
|
||||
'../core/src/usage_table_header.cpp',
|
||||
'../core/src/wv_cdm_types.cpp',
|
||||
'../metrics/src/attribute_handler.cpp',
|
||||
'../metrics/src/counter_metric.cpp',
|
||||
'../metrics/src/distribution.cpp',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
#source code may only be used and distributed under the Widevine Master License
|
||||
#source code may only be used and distributed under the Widevine License
|
||||
#Agreement.
|
||||
#
|
||||
# Include this in any custom unit test targets.
|
||||
@@ -14,19 +14,25 @@
|
||||
'../core/test/certificate_provisioning_unittest.cpp',
|
||||
'../core/test/crypto_session_unittest.cpp',
|
||||
'../core/test/device_files_unittest.cpp',
|
||||
'../core/test/duration_use_case_test.cpp',
|
||||
'../core/test/fake_provisioning_server.cpp',
|
||||
'../core/test/generic_crypto_unittest.cpp',
|
||||
'../core/test/http_socket.cpp',
|
||||
'../core/test/http_socket_test.cpp',
|
||||
'../core/test/initialization_data_unittest.cpp',
|
||||
'../core/test/license_holder.cpp',
|
||||
'../core/test/license_keys_unittest.cpp',
|
||||
'../core/test/license_request.cpp',
|
||||
'../core/test/license_unittest.cpp',
|
||||
'../core/test/okp_fallback_policy_test.cpp',
|
||||
'../core/test/ota_keybox_provisioner_test.cpp',
|
||||
'../core/test/parallel_operations_test.cpp',
|
||||
'../core/test/policy_engine_constraints_unittest.cpp',
|
||||
'../core/test/policy_engine_unittest.cpp',
|
||||
'../core/test/policy_integration_test.cpp',
|
||||
'../core/test/rw_lock_test.cpp',
|
||||
'../core/test/service_certificate_unittest.cpp',
|
||||
'../core/test/system_id_extractor_unittest.cpp',
|
||||
'../core/test/test_base.cpp',
|
||||
'../core/test/test_printers.cpp',
|
||||
'../core/test/url_request.cpp',
|
||||
|
||||
30
cdm/create_cert_cc.py
Executable file
30
cdm/create_cert_cc.py
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/python3
|
||||
# Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
|
||||
"""Creates a cert.cc file from a cert.bin file."""
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('input')
|
||||
parser.add_argument('output')
|
||||
parser.add_argument('--variable', default='DeviceCert')
|
||||
|
||||
options = parser.parse_args(sys.argv[1:])
|
||||
in_path = pathlib.Path(options.input)
|
||||
dat = ', '.join(str(x) for x in in_path.read_bytes())
|
||||
out_path = pathlib.Path(options.output)
|
||||
out_path.write_text(f"""// Copyright 2021 Google LLC. All Rights Reserved.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
extern const uint8_t k{options.variable}[];
|
||||
const uint8_t k{options.variable}[] = {{ {dat} }};
|
||||
|
||||
extern const size_t k{options.variable}Size;
|
||||
const size_t k{options.variable}Size = sizeof(k{options.variable});""")
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
// Based on the EME draft spec from 2016 June 10.
|
||||
// http://www.w3.org/TR/2016/WD-encrypted-media-20160610/"
|
||||
#ifndef WVCDM_CDM_CDM_H_
|
||||
@@ -31,12 +31,13 @@ namespace widevine {
|
||||
|
||||
class CDM_EXPORT ITimerClient {
|
||||
public:
|
||||
virtual ~ITimerClient() {}
|
||||
|
||||
// Called by ITimer when a timer expires.
|
||||
virtual void onTimerExpired(void* context) = 0;
|
||||
|
||||
protected:
|
||||
ITimerClient() {}
|
||||
virtual ~ITimerClient() {}
|
||||
};
|
||||
|
||||
class CDM_EXPORT Cdm : public ITimerClient {
|
||||
@@ -194,6 +195,14 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
kL3 = 3,
|
||||
};
|
||||
|
||||
// Status code returned by getProvisioningStatus API.
|
||||
enum ProvisioningStatus : int32_t {
|
||||
kProvisioned = 0,
|
||||
kUnknownProvisionStatus = 1,
|
||||
kNeedsDrmCertProvisioning = 2,
|
||||
kNeedsOemCertProvisioning = 3,
|
||||
};
|
||||
|
||||
// A map of key statuses.
|
||||
// See Cdm::getKeyStatuses().
|
||||
typedef std::map<std::string, KeyStatus> KeyStatusMap;
|
||||
@@ -203,6 +212,8 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// See Cdm::createSession().
|
||||
class IEventListener {
|
||||
public:
|
||||
virtual ~IEventListener() {}
|
||||
|
||||
// A message (license request, renewal, etc.) to be dispatched to the
|
||||
// application's license server.
|
||||
// The response, if successful, should be provided back to the CDM via a
|
||||
@@ -220,7 +231,6 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
|
||||
protected:
|
||||
IEventListener() {}
|
||||
virtual ~IEventListener() {}
|
||||
};
|
||||
|
||||
// A storage interface provided by the application. This defines the "origin"
|
||||
@@ -240,6 +250,8 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo.
|
||||
class IStorage {
|
||||
public:
|
||||
virtual ~IStorage() {}
|
||||
|
||||
virtual bool read(const std::string& name, std::string* data) = 0;
|
||||
virtual bool write(const std::string& name, const std::string& data) = 0;
|
||||
virtual bool exists(const std::string& name) = 0;
|
||||
@@ -256,7 +268,6 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
|
||||
protected:
|
||||
IStorage() {}
|
||||
virtual ~IStorage() {}
|
||||
};
|
||||
|
||||
// A clock interface provided by the application, independent of CDM
|
||||
@@ -264,12 +275,13 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// See Cdm::initialize().
|
||||
class IClock {
|
||||
public:
|
||||
virtual ~IClock() {}
|
||||
|
||||
// Returns the current time in milliseconds since 1970 UTC.
|
||||
virtual int64_t now() = 0;
|
||||
|
||||
protected:
|
||||
IClock() {}
|
||||
virtual ~IClock() {}
|
||||
};
|
||||
|
||||
// A timer interface provided by the application, independent of CDM
|
||||
@@ -284,6 +296,8 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// setTimeout() again inside the timeout callback.
|
||||
class ITimer {
|
||||
public:
|
||||
virtual ~ITimer() {}
|
||||
|
||||
// This typedef is for backward compatibility with v3.0.0.
|
||||
typedef ITimerClient IClient;
|
||||
|
||||
@@ -296,38 +310,40 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
|
||||
protected:
|
||||
ITimer() {}
|
||||
virtual ~ITimer() {}
|
||||
};
|
||||
|
||||
// Client information, provided by the application, independent of CDM
|
||||
// instances.
|
||||
// See Cdm::initialize().
|
||||
// These parameters end up as client identification in license requests.
|
||||
// All fields may be used by a license server proxy to drive business logic.
|
||||
// Some fields are required (indicated below), but please fill out as many
|
||||
// as make sense for your application.
|
||||
// No user-identifying information may be put in these fields!
|
||||
// The CE CDM has various pieces of client information baked into it at
|
||||
// compile-time. These can be retrieved at runtime by Cdm::getClientInfo(),
|
||||
// which returns them in this struct.
|
||||
// These parameters match the client identification in license requests.
|
||||
struct ClientInfo {
|
||||
// The name of the product or application, e.g. "TurtleTube"
|
||||
// Required.
|
||||
std::string product_name;
|
||||
|
||||
// The name of the company who makes the device, e.g. "Kubrick, Inc."
|
||||
// Required.
|
||||
// The name of the company who makes the client, e.g. "KubrickTech".
|
||||
// This matches the "Make" field in the Widevine Integration Console.
|
||||
std::string company_name;
|
||||
|
||||
// The name of the device, e.g. "HAL"
|
||||
std::string device_name;
|
||||
|
||||
// The device model, e.g. "HAL 9000"
|
||||
// Required.
|
||||
// The client's model name, e.g. "HAL 9000".
|
||||
// This matches the "Model" field in the Widevine Integration Console.
|
||||
std::string model_name;
|
||||
|
||||
// The architecture of the device, e.g. "x86-64"
|
||||
// The client's model year, e.g. "2001".
|
||||
// Can be used to distinguish different devices with the same model name.
|
||||
// This matches the "Year" field in the Widevine Integration Console.
|
||||
std::string model_year;
|
||||
|
||||
// The name or codename of the product or application, e.g. "clarke".
|
||||
// This may be the same as "model_name".
|
||||
std::string product_name;
|
||||
|
||||
// The name or codename of the client, e.g. "HAL".
|
||||
// This may be the same as "model_name" or "product_name".
|
||||
std::string device_name;
|
||||
|
||||
// The CPU architecture of the client, e.g. "ARMv7".
|
||||
std::string arch_name;
|
||||
|
||||
// Information about the build of the browser, application, or platform into
|
||||
// which the CDM is integrated, e.g. "v2.71828, 2038-01-19-03:14:07"
|
||||
// A string containing build information about the CE CDM and the client
|
||||
// it's integrated into. Consists of multiple values separated by spaces
|
||||
// and vertical pipes. (e.g. " | ")
|
||||
std::string build_info;
|
||||
};
|
||||
|
||||
@@ -338,21 +354,23 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// Logging is controlled by |verbosity|.
|
||||
// Must be called and must return kSuccess before create() is called.
|
||||
static Status initialize(SecureOutputType secure_output_type,
|
||||
const ClientInfo& client_info, IStorage* storage,
|
||||
IClock* clock, ITimer* timer, LogLevel verbosity);
|
||||
IStorage* storage, IClock* clock, ITimer* timer,
|
||||
LogLevel verbosity);
|
||||
|
||||
// This is a variant of the above function that allows the caller to pass a
|
||||
// Sandbox ID. Platforms that use Sandbox IDs should use this initalize()
|
||||
// function instead of the previous one. Platforms that do not use Sandbox IDs
|
||||
// should not use this version of initialize().
|
||||
static Status initialize(SecureOutputType secure_output_type,
|
||||
const ClientInfo& client_info, IStorage* storage,
|
||||
IClock* clock, ITimer* timer, LogLevel verbosity,
|
||||
const std::string& sandbox_id);
|
||||
IStorage* storage, IClock* clock, ITimer* timer,
|
||||
LogLevel verbosity, const std::string& sandbox_id);
|
||||
|
||||
// Query the CDM library version.
|
||||
static const char* version();
|
||||
|
||||
// Retrieves the client information for this CE CDM integration.
|
||||
static Status getClientInfo(ClientInfo* client_info);
|
||||
|
||||
// Constructs a new CDM instance.
|
||||
// initialize() must be called first and must return kSuccess before a CDM
|
||||
// instance may be constructed.
|
||||
@@ -387,7 +405,7 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
static Cdm* create(IEventListener* listener, IStorage* storage,
|
||||
bool privacy_mode, bool storage_is_read_only);
|
||||
|
||||
virtual ~Cdm() {}
|
||||
~Cdm() override {}
|
||||
|
||||
// The following three methods relate to service certificates. A service
|
||||
// certificate holds the RSA public key for a server, as well as other fields
|
||||
@@ -449,6 +467,9 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// and the license service should be used to make security decisions.
|
||||
virtual Status getRobustnessLevel(RobustnessLevel* level) = 0;
|
||||
|
||||
// Query the underlying OEMCrypto implementation's System ID.
|
||||
virtual Status getSystemId(uint32_t* id) = 0;
|
||||
|
||||
// Returns the resource rating tier of the device, as reported by OEMCrypto.
|
||||
virtual Status getResourceRatingTier(uint32_t* tier) = 0;
|
||||
|
||||
@@ -456,10 +477,10 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// implementation.
|
||||
virtual Status getOemCryptoBuildInfo(std::string* build_info) = 0;
|
||||
|
||||
// Determine if the device has a Device Certificate (for the current origin).
|
||||
// The Device Certificate is origin-specific, and the origin is
|
||||
// dertermined by the CDM's current IStorage object.
|
||||
virtual bool isProvisioned() = 0;
|
||||
// Retrieves the current provisioning status. The Device Certificate is
|
||||
// origin-specific, and the origin is determined by the CDM's current IStorage
|
||||
// object.
|
||||
virtual ProvisioningStatus getProvisioningStatus() = 0;
|
||||
|
||||
// Creates a Provisioning Request message.
|
||||
// This is used to provision the device. The request should be sent to the
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
// Copyright 2015 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#define CDM_VERSION_STR_(x, y, z, w) #x "." #y "." #z w
|
||||
#define CDM_VERSION_STR(x, y, z, w) CDM_VERSION_STR_(x, y, z, w)
|
||||
|
||||
// Widevine CE CDM Version
|
||||
#ifndef CDM_VERSION
|
||||
# define CDM_VERSION "16.4.0"
|
||||
#ifndef CDM_VERSION_MAJOR
|
||||
# define CDM_VERSION_MAJOR 17
|
||||
#endif
|
||||
#ifndef CDM_VERSION_MINOR
|
||||
# define CDM_VERSION_MINOR 1
|
||||
#endif
|
||||
#ifndef CDM_VERSION_PATCH
|
||||
# define CDM_VERSION_PATCH 0
|
||||
#endif
|
||||
#ifndef CDM_VERSION_TAG
|
||||
# define CDM_VERSION_TAG ""
|
||||
#endif
|
||||
#define CDM_VERSION \
|
||||
CDM_VERSION_STR(CDM_VERSION_MAJOR, CDM_VERSION_MINOR, CDM_VERSION_PATCH, \
|
||||
CDM_VERSION_TAG)
|
||||
|
||||
#define EME_VERSION "https://www.w3.org/TR/2017/REC-encrypted-media-20170918"
|
||||
|
||||
42
cdm/include/compiler_detection.h
Normal file
42
cdm/include/compiler_detection.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#ifndef WVCDM_CDM_COMPILER_DETECTION_H_
|
||||
#define WVCDM_CDM_COMPILER_DETECTION_H_
|
||||
|
||||
// This file makes some best-effort attempts to detect details about the
|
||||
// compilation environment used by CacheBuildInfo.
|
||||
|
||||
#if defined(CDM_DISABLE_LOGGING)
|
||||
# define LOGGING_MESSAGE "Logging Disabled"
|
||||
#else
|
||||
# define LOGGING_MESSAGE "Logging Enabled"
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG)
|
||||
# define BUILD_FLAVOR_MESSAGE "Debug"
|
||||
#elif defined(NDEBUG)
|
||||
# define BUILD_FLAVOR_MESSAGE "Release"
|
||||
#else
|
||||
# define BUILD_FLAVOR_MESSAGE "Unknown"
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
# define CPU_ARCH_MESSAGE "x86-64"
|
||||
#elif defined(__i386__) || defined(_M_IX86)
|
||||
# define CPU_ARCH_MESSAGE "i386"
|
||||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||
# define CPU_ARCH_MESSAGE "AArch64"
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
# define CPU_ARCH_MESSAGE "AArch32"
|
||||
#elif defined(__mips__)
|
||||
# define CPU_ARCH_MESSAGE "MIPS"
|
||||
#elif defined(__powerpc64__)
|
||||
# define CPU_ARCH_MESSAGE "64-bit PowerPC"
|
||||
#elif defined(__powerpc__) || defined(_M_PPC)
|
||||
# define CPU_ARCH_MESSAGE "32-bit PowerPC"
|
||||
#else
|
||||
# define CPU_ARCH_MESSAGE "Unrecognized CPU"
|
||||
#endif
|
||||
|
||||
#endif // WVCDM_CDM_COMPILER_DETECTION_H_
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#ifndef WVCDM_CDM_PROPERTIES_CE_H_
|
||||
#define WVCDM_CDM_PROPERTIES_CE_H_
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace widevine {
|
||||
|
||||
class PropertiesCE {
|
||||
public:
|
||||
static Cdm::ClientInfo GetClientInfo();
|
||||
static Cdm::SecureOutputType GetSecureOutputType();
|
||||
static void SetProvisioningMessagesAreBinary(bool bin_prov);
|
||||
// If this is set to an empty string, (which is the default) then PropertiesCE
|
||||
@@ -23,7 +22,6 @@ class PropertiesCE {
|
||||
|
||||
private:
|
||||
static void SetSecureOutputType(Cdm::SecureOutputType secure_output_type);
|
||||
static void SetClientInfo(const Cdm::ClientInfo& client_info);
|
||||
|
||||
friend class Cdm;
|
||||
#if defined(UNIT_TEST)
|
||||
|
||||
35
cdm/oemcrypto_reference_implementation.gyp
Normal file
35
cdm/oemcrypto_reference_implementation.gyp
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
{
|
||||
'includes': [
|
||||
'platform_properties.gypi',
|
||||
],
|
||||
'variables': {
|
||||
# Directory where OEMCrypto header, test, and reference files lives.
|
||||
'oemcrypto_dir': '../oemcrypto',
|
||||
# Directory where widevine utilities live.
|
||||
'util_dir': '../util',
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'oec_ref',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'includes': [
|
||||
'../oemcrypto/ref/oec_ref.gypi',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(oemcrypto_dir)/util/oec_ref_util.gyp:oec_ref_util',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'oec_ref_shared',
|
||||
'type': 'shared_library',
|
||||
'dependencies': [
|
||||
'oec_ref'
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine Master
|
||||
# License Agreement.
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
|
||||
# This file contains all the variables that Widevine exposes for integration
|
||||
# partners to customize in their platforms' settings.gypi files. Partners will
|
||||
@@ -16,6 +16,44 @@
|
||||
# achieve.
|
||||
{
|
||||
'variables': {
|
||||
# The following variables define the client info that is baked into the CDM
|
||||
# binary at build-time. These parameters end up as client identification in
|
||||
# license requests. All values may be used by a license server proxy to
|
||||
# drive business logic. You *must* set meaningful values for all of these
|
||||
# variables as part of defining your platform. Values may not contain
|
||||
# double quotes, percent signs, or the substring " | ". (a vertical pipe
|
||||
# surrounded by spaces)
|
||||
|
||||
# The name of the company who makes the client, e.g. "KubrickTech".
|
||||
# This should match the "Make" field in the Widevine Integration Console.
|
||||
'client_company_name%': '',
|
||||
# The client's model name, e.g. "HAL 9000".
|
||||
# This should match the "Model" field in the Widevine Integration Console.
|
||||
'client_model_name%': '',
|
||||
# The client's model year, e.g. "2001".
|
||||
# Can be used to distinguish different devices with the same model name.
|
||||
# This should match the "Year" field in the Widevine Integration Console.
|
||||
'client_model_year%': '',
|
||||
# The name or codename of the product or application, e.g. "clarke".
|
||||
# This may be the same as "client_model_name".
|
||||
'client_product_name%': '',
|
||||
# The name or codename of the client, e.g. "HAL".
|
||||
# This may be the same as "client_model_name" or "client_product_name".
|
||||
'client_device_name%': '',
|
||||
# The CPU architecture of the client, e.g. "ARMv7".
|
||||
'client_arch_name%': '',
|
||||
# The OS platform of the client, e.g. "Linux".
|
||||
# This should match the "Platform" field in the Widevine Integration
|
||||
# Console.
|
||||
'client_platform%': '',
|
||||
# The form factor of the client, e.g. "TV".
|
||||
# This should match the "Type" field in the Widevine Integration Console.
|
||||
'client_form_factor%': '',
|
||||
# The version number of the client that the CE CDM is integrated into. This
|
||||
# is the operating system or app version, not the CDM version.
|
||||
'client_version%': '',
|
||||
|
||||
|
||||
# Choose type of OEMCrypto library to compile in. Valid values are:
|
||||
#
|
||||
# 'vendor' - Production Level 1 systems should use 'vendor' to indicate that
|
||||
@@ -47,6 +85,12 @@
|
||||
# other values - for internal testing.
|
||||
'oemcrypto_adapter_type%': 'static',
|
||||
|
||||
# Whether to include OTA Keybox functionality or not. This is an optional
|
||||
# feature that is only used a few platforms. Generally, to qualify as an L1
|
||||
# device, a keybox must be installed on the device in the factory.
|
||||
# Valid values are 'true' or 'false'.
|
||||
'support_ota_keybox_functions%': 'false',
|
||||
|
||||
# Override this to indicate what CPU architecture's assembly-language files
|
||||
# should be used when building assembly language files. Or, set it to
|
||||
# "none" to turn off the use of assembly language. The default is "none" for
|
||||
@@ -58,7 +102,7 @@
|
||||
#
|
||||
# Valid values are:
|
||||
# * x86
|
||||
# * x86-64
|
||||
# * x64 or x86-64
|
||||
# * arm
|
||||
# * arm64
|
||||
# * ppc64
|
||||
@@ -96,8 +140,8 @@
|
||||
# When using BoringSSL, the Widevine CE CDM defaults to the copy of
|
||||
# BoringSSL in third_party/boringssl/. If you have an alternative BoringSSL
|
||||
# GYP build, you can override these variables to point to it instead.
|
||||
'boringssl_libcrypto_path%': '../third_party/boringssl/boringssl.gyp:crypto',
|
||||
'boringssl_libssl_path%': '../third_party/boringssl/boringssl.gyp:ssl',
|
||||
'boringssl_libcrypto_path%': '<(DEPTH)/third_party/boringssl/boringssl.gyp:crypto',
|
||||
'boringssl_libssl_path%': '<(DEPTH)/third_party/boringssl/boringssl.gyp:ssl',
|
||||
|
||||
# There are three protobuf configurations:
|
||||
#
|
||||
@@ -113,10 +157,29 @@
|
||||
# Specify the path to protoc in protoc_bin.
|
||||
#
|
||||
# 3) protobuf_config == 'source' (default)
|
||||
# Build protobuf and protoc from source.
|
||||
# Specify the path to the protobuf source in protobuf_source.
|
||||
# Build protobuf and protoc from the copy in third_party/protobuf.
|
||||
'protobuf_config%': 'source',
|
||||
'protobuf_source%': '../third_party/protobuf',
|
||||
'protoc_host_target%': 'dummy',
|
||||
'protoc_bin%': '',
|
||||
'protoc_lib%': '',
|
||||
'protoc_lib_target%': '',
|
||||
'protoc_host_target%': '',
|
||||
}, # variables
|
||||
|
||||
# This block defines preprocessor values that match the client information
|
||||
# variables above. If you are writing your own build files to build CE CDM
|
||||
# insted of using these GYP files, make sure to define these values, following
|
||||
# the rules in the client info section above.
|
||||
'target_defaults': {
|
||||
'defines': [
|
||||
'CLIENT_COMPANY_NAME="<(client_company_name)"',
|
||||
'CLIENT_MODEL_NAME="<(client_model_name)"',
|
||||
'CLIENT_MODEL_YEAR="<(client_model_year)"',
|
||||
'CLIENT_PRODUCT_NAME="<(client_product_name)"',
|
||||
'CLIENT_DEVICE_NAME="<(client_device_name)"',
|
||||
'CLIENT_ARCH_NAME="<(client_arch_name)"',
|
||||
'CLIENT_PLATFORM="<(client_platform)"',
|
||||
'CLIENT_FORM_FACTOR="<(client_form_factor)"',
|
||||
'CLIENT_VERSION="<(client_version)"',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
159
cdm/src/cdm.cpp
159
cdm/src/cdm.cpp
@@ -1,11 +1,11 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#include "cdm.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h> // LLONG_MAX
|
||||
#include <string.h> // memcpy
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -37,13 +37,50 @@
|
||||
namespace widevine {
|
||||
|
||||
using namespace wvcdm;
|
||||
using namespace wvutil;
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char* kNoSandboxId = "";
|
||||
constexpr char kNoSandboxId[] = "";
|
||||
const int64_t kPolicyTimerDurationMilliseconds = 5000;
|
||||
void* const kPolicyTimerContext = nullptr;
|
||||
|
||||
#define STRINGIFY(PARAM) #PARAM
|
||||
|
||||
bool isClientInfoValid(const char* tag, const char* value) {
|
||||
constexpr char kForbiddenSeparator[] = " | ";
|
||||
constexpr char kForbiddenPercent[] = "%";
|
||||
if (value[0] == '\0') {
|
||||
LOGE("%s may not be empty, but it is.", tag);
|
||||
return false;
|
||||
}
|
||||
if (strstr(value, kForbiddenSeparator) != nullptr) {
|
||||
LOGE("%s may not contain \"%s\", but it's \"%s\"", tag, kForbiddenSeparator,
|
||||
value);
|
||||
return false;
|
||||
}
|
||||
if (strstr(value, kForbiddenPercent) != nullptr) {
|
||||
LOGE("%s may not contain \"%s\", but it's \"%s\"", tag, kForbiddenPercent,
|
||||
value);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool clientInfoIsValid() {
|
||||
return isClientInfoValid(STRINGIFY(CLIENT_COMPANY_NAME),
|
||||
CLIENT_COMPANY_NAME) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_MODEL_NAME), CLIENT_MODEL_NAME) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_MODEL_YEAR), CLIENT_MODEL_YEAR) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_PRODUCT_NAME),
|
||||
CLIENT_PRODUCT_NAME) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_DEVICE_NAME), CLIENT_DEVICE_NAME) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_ARCH_NAME), CLIENT_ARCH_NAME) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_PLATFORM), CLIENT_PLATFORM) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_FORM_FACTOR), CLIENT_FORM_FACTOR) &&
|
||||
isClientInfoValid(STRINGIFY(CLIENT_VERSION), CLIENT_VERSION);
|
||||
}
|
||||
|
||||
struct HostType {
|
||||
Cdm::IStorage* storage;
|
||||
Cdm::IClock* clock;
|
||||
@@ -197,11 +234,13 @@ class CdmImpl final : public Cdm, public WvCdmEventListener {
|
||||
|
||||
Status getRobustnessLevel(RobustnessLevel* level) override;
|
||||
|
||||
Status getSystemId(uint32_t* id) override;
|
||||
|
||||
Status getResourceRatingTier(uint32_t* tier) override;
|
||||
|
||||
Status getOemCryptoBuildInfo(std::string* build_info) override;
|
||||
|
||||
bool isProvisioned() override;
|
||||
ProvisioningStatus getProvisioningStatus() override;
|
||||
|
||||
Status getProvisioningRequest(std::string* request) override;
|
||||
|
||||
@@ -446,6 +485,27 @@ Cdm::Status CdmImpl::getRobustnessLevel(RobustnessLevel* level) {
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Cdm::Status CdmImpl::getSystemId(uint32_t* id) {
|
||||
if (id == nullptr) {
|
||||
LOGE("Missing id parameter to receive system ID.");
|
||||
return kTypeError;
|
||||
}
|
||||
|
||||
std::string id_string;
|
||||
const CdmResponseType result =
|
||||
cdm_engine_->QueryStatus(kLevelDefault, QUERY_KEY_SYSTEM_ID, &id_string);
|
||||
if (result == SYSTEM_INVALIDATED_ERROR) {
|
||||
LOGE("System invalidated");
|
||||
return kSystemStateLost;
|
||||
} else if (result != NO_ERROR) {
|
||||
LOGE("Unexpected error %d", static_cast<int>(result));
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
*id = static_cast<uint32_t>(std::stoul(id_string));
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Cdm::Status CdmImpl::getResourceRatingTier(uint32_t* tier) {
|
||||
if (tier == nullptr) {
|
||||
LOGE("Missing tier parameter to receive resource rating tier.");
|
||||
@@ -492,8 +552,22 @@ Cdm::Status CdmImpl::getOemCryptoBuildInfo(std::string* build_info) {
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
bool CdmImpl::isProvisioned() {
|
||||
return cdm_engine_->IsProvisioned(kSecurityLevelL1);
|
||||
Cdm::ProvisioningStatus CdmImpl::getProvisioningStatus() {
|
||||
const CdmProvisioningStatus status =
|
||||
cdm_engine_->GetProvisioningStatus(kSecurityLevelL1);
|
||||
switch (status) {
|
||||
case CdmProvisioningStatus::kProvisioned:
|
||||
return kProvisioned;
|
||||
case CdmProvisioningStatus::kNeedsDrmCertProvisioning:
|
||||
return kNeedsDrmCertProvisioning;
|
||||
case CdmProvisioningStatus::kNeedsOemCertProvisioning:
|
||||
return kNeedsOemCertProvisioning;
|
||||
case CdmProvisioningStatus::kUnknownProvisionStatus:
|
||||
LOGW("Unknown provisioning status");
|
||||
return kUnknownProvisionStatus;
|
||||
}
|
||||
LOGE("Unexpected provisioning status %d", static_cast<int>(status));
|
||||
return kUnknownProvisionStatus;
|
||||
}
|
||||
|
||||
Cdm::Status CdmImpl::getProvisioningRequest(std::string* request) {
|
||||
@@ -1654,17 +1728,16 @@ Cdm::Status CdmImpl::ConvertHdcpLevel(const std::string& query_value,
|
||||
|
||||
// static
|
||||
Cdm::Status Cdm::initialize(SecureOutputType secure_output_type,
|
||||
const ClientInfo& client_info, IStorage* storage,
|
||||
IClock* clock, ITimer* timer, LogLevel verbosity) {
|
||||
return initialize(secure_output_type, client_info, storage, clock, timer,
|
||||
verbosity, kNoSandboxId);
|
||||
IStorage* storage, IClock* clock, ITimer* timer,
|
||||
LogLevel verbosity) {
|
||||
return initialize(secure_output_type, storage, clock, timer, verbosity,
|
||||
kNoSandboxId);
|
||||
}
|
||||
|
||||
// static
|
||||
Cdm::Status Cdm::initialize(SecureOutputType secure_output_type,
|
||||
const ClientInfo& client_info, IStorage* storage,
|
||||
IClock* clock, ITimer* timer, LogLevel verbosity,
|
||||
const std::string& sandbox_id) {
|
||||
IStorage* storage, IClock* clock, ITimer* timer,
|
||||
LogLevel verbosity, const std::string& sandbox_id) {
|
||||
// Specify the maximum severity of message that will be output to
|
||||
// the console. See core/include/log.h for the valid priority values.
|
||||
g_cutoff = static_cast<LogPriority>(verbosity);
|
||||
@@ -1679,11 +1752,7 @@ Cdm::Status Cdm::initialize(SecureOutputType secure_output_type,
|
||||
return kTypeError;
|
||||
}
|
||||
|
||||
if (client_info.product_name.empty() || client_info.company_name.empty() ||
|
||||
client_info.model_name.empty()) {
|
||||
LOGE("Client info requires product_name, company_name, model_name!");
|
||||
return kTypeError;
|
||||
}
|
||||
if (!clientInfoIsValid()) return kUnexpectedError;
|
||||
|
||||
if (!storage || !clock || !timer) {
|
||||
LOGE("All interfaces are required!");
|
||||
@@ -1691,7 +1760,6 @@ Cdm::Status Cdm::initialize(SecureOutputType secure_output_type,
|
||||
}
|
||||
|
||||
PropertiesCE::SetSecureOutputType(secure_output_type);
|
||||
PropertiesCE::SetClientInfo(client_info);
|
||||
if (sandbox_id != kNoSandboxId) PropertiesCE::SetSandboxId(sandbox_id);
|
||||
Properties::Init();
|
||||
host.storage = storage;
|
||||
@@ -1704,6 +1772,53 @@ Cdm::Status Cdm::initialize(SecureOutputType secure_output_type,
|
||||
// static
|
||||
const char* Cdm::version() { return CDM_VERSION; }
|
||||
|
||||
// static
|
||||
Cdm::Status Cdm::getClientInfo(ClientInfo* client_info) {
|
||||
if (client_info == nullptr) {
|
||||
LOGE("Missing client_info parameter.");
|
||||
return kTypeError;
|
||||
}
|
||||
|
||||
if (!clientInfoIsValid()) return kUnexpectedError;
|
||||
|
||||
if (!Properties::GetCompanyName(&client_info->company_name)) {
|
||||
LOGE("Unable to get Company Name.");
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
if (!Properties::GetModelName(&client_info->model_name)) {
|
||||
LOGE("Unable to get Model Name.");
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
if (!Properties::GetModelYear(&client_info->model_year)) {
|
||||
LOGE("Unable to get Model Year.");
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
if (!Properties::GetDeviceName(&client_info->device_name)) {
|
||||
LOGE("Unable to get Device Name.");
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
if (!Properties::GetProductName(&client_info->product_name)) {
|
||||
LOGE("Unable to get Product Name.");
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
if (!Properties::GetArchitectureName(&client_info->arch_name)) {
|
||||
LOGE("Unable to get Architecture Name.");
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
if (!Properties::GetBuildInfo(&client_info->build_info)) {
|
||||
LOGE("Unable to get Build Info.");
|
||||
return kUnexpectedError;
|
||||
}
|
||||
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
// static
|
||||
Cdm* Cdm::create(IEventListener* listener, IStorage* storage,
|
||||
bool privacy_mode) {
|
||||
@@ -1739,7 +1854,7 @@ Cdm* Cdm::create(IEventListener* listener, IStorage* storage, bool privacy_mode,
|
||||
} // namespace widevine
|
||||
|
||||
// Missing symbols from core:
|
||||
namespace wvcdm {
|
||||
namespace wvutil {
|
||||
|
||||
using namespace widevine;
|
||||
|
||||
@@ -1840,4 +1955,4 @@ bool FileSystem::List(const std::string&,
|
||||
return file_names && impl_->storage_->list(file_names);
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
} // namespace wvutil
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
//
|
||||
// Log - implemented using stderr.
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace wvcdm {
|
||||
namespace wvutil {
|
||||
|
||||
LogPriority g_cutoff = LOG_WARN;
|
||||
LogPriority g_cutoff = CDM_LOG_WARN;
|
||||
|
||||
void InitLogging() {}
|
||||
|
||||
@@ -39,4 +39,4 @@ void Log(const char* file, const char* function, int line, LogPriority level,
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
} // namespace wvutil
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#include "properties_ce.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "cdm_version.h"
|
||||
#include "compiler_detection.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
|
||||
@@ -19,16 +25,20 @@ std::string sandbox_id_;
|
||||
|
||||
widevine::Cdm::SecureOutputType secure_output_type_ =
|
||||
widevine::Cdm::kNoSecureOutput;
|
||||
widevine::Cdm::ClientInfo client_info_;
|
||||
|
||||
bool GetValue(const std::string& source, std::string* output) {
|
||||
if (!output) {
|
||||
bool GetValue(const char* source, std::string* output) {
|
||||
if (!source || !output) {
|
||||
return false;
|
||||
}
|
||||
*output = source;
|
||||
return source.size() != 0;
|
||||
return source[0] != '\0';
|
||||
}
|
||||
|
||||
constexpr char kBuildInfo[] = CLIENT_VERSION
|
||||
" | " CLIENT_PLATFORM " | " CLIENT_FORM_FACTOR " | " CLIENT_ARCH_NAME
|
||||
" | CE CDM " CDM_VERSION " | " CPU_ARCH_MESSAGE " | " LOGGING_MESSAGE
|
||||
" | " BUILD_FLAVOR_MESSAGE;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace widevine {
|
||||
@@ -63,14 +73,6 @@ Cdm::SecureOutputType PropertiesCE::GetSecureOutputType() {
|
||||
return secure_output_type_;
|
||||
}
|
||||
|
||||
// static
|
||||
void PropertiesCE::SetClientInfo(const Cdm::ClientInfo& client_info) {
|
||||
client_info_ = client_info;
|
||||
}
|
||||
|
||||
// static
|
||||
Cdm::ClientInfo PropertiesCE::GetClientInfo() { return client_info_; }
|
||||
|
||||
// static
|
||||
void PropertiesCE::SetProvisioningMessagesAreBinary(bool new_setting) {
|
||||
set_provisioning_messages_to_binary_ = new_setting;
|
||||
@@ -100,32 +102,37 @@ void Properties::InitOnce() {
|
||||
|
||||
// static
|
||||
bool Properties::GetCompanyName(std::string* company_name) {
|
||||
return GetValue(client_info_.company_name, company_name);
|
||||
return GetValue(CLIENT_COMPANY_NAME, company_name);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Properties::GetModelName(std::string* model_name) {
|
||||
return GetValue(client_info_.model_name, model_name);
|
||||
return GetValue(CLIENT_MODEL_NAME, model_name);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Properties::GetModelYear(std::string* model_year) {
|
||||
return GetValue(CLIENT_MODEL_YEAR, model_year);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Properties::GetArchitectureName(std::string* arch_name) {
|
||||
return GetValue(client_info_.arch_name, arch_name);
|
||||
return GetValue(CLIENT_ARCH_NAME, arch_name);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Properties::GetDeviceName(std::string* device_name) {
|
||||
return GetValue(client_info_.device_name, device_name);
|
||||
return GetValue(CLIENT_DEVICE_NAME, device_name);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Properties::GetProductName(std::string* product_name) {
|
||||
return GetValue(client_info_.product_name, product_name);
|
||||
return GetValue(CLIENT_PRODUCT_NAME, product_name);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Properties::GetBuildInfo(std::string* build_info) {
|
||||
return GetValue(client_info_.build_info, build_info);
|
||||
return GetValue(kBuildInfo, build_info);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -151,7 +158,13 @@ bool Properties::GetFactoryKeyboxPath(std::string*) {
|
||||
// static
|
||||
bool Properties::GetOEMCryptoPath(std::string* path) {
|
||||
if (path == nullptr) return false;
|
||||
*path = "liboemcrypto.so";
|
||||
// Using an environment variable is useful for testing.
|
||||
const char* env_path = getenv("LIBOEMCRYPTO_PATH");
|
||||
if (env_path) {
|
||||
*path = std::string(env_path);
|
||||
} else {
|
||||
*path = "liboemcrypto.so";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
118
cdm/test/cdm_reboot_test_main.cpp
Normal file
118
cdm/test/cdm_reboot_test_main.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <assert.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#include "cdm.h"
|
||||
#include "cdm_test_runner.h"
|
||||
#include "clock.h"
|
||||
#include "device_cert.h"
|
||||
#include "log.h"
|
||||
#include "reboot_test.h"
|
||||
#include "test_base.h"
|
||||
#include "test_host.h"
|
||||
|
||||
using namespace widevine;
|
||||
|
||||
// TODO(b/195338975): document how a partner should modify this so that they can
|
||||
// use a real host.
|
||||
TestHost* g_host = nullptr;
|
||||
|
||||
namespace {
|
||||
constexpr char kGlobalDumpFileName[] = "dumped_global_filesystem.dat";
|
||||
constexpr char kPerOriginDumpFileName[] = "dumped_per_origin_filesystem.dat";
|
||||
|
||||
using StorageMap = TestHost::Storage::StorageMap;
|
||||
|
||||
// Load a TestHost file system from the real file system.
|
||||
bool ReloadFileSystem(const char* file_name, StorageMap* map) {
|
||||
std::ifstream input(file_name);
|
||||
if (input.fail()) {
|
||||
// This is OK for first pass, but an error for later passes.
|
||||
LOGD("Could not read %s", file_name);
|
||||
return false;
|
||||
}
|
||||
std::string dumped_file_system((std::istreambuf_iterator<char>(input)),
|
||||
std::istreambuf_iterator<char>());
|
||||
if (!wvcdm::RebootTest::ParseDump(dumped_file_system, map)) {
|
||||
LOGE("Could not parse %s", file_name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReloadFileSystems() {
|
||||
StorageMap global_map;
|
||||
StorageMap per_origin_map;
|
||||
if (!ReloadFileSystem(kGlobalDumpFileName, &global_map) ||
|
||||
!ReloadFileSystem(kPerOriginDumpFileName, &per_origin_map)) {
|
||||
return false;
|
||||
}
|
||||
g_host->global_storage().ResetFiles(global_map);
|
||||
g_host->per_origin_storage().ResetFiles(per_origin_map);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Dump a TestHost file system to the real file system. If the dump file
|
||||
// cannot be written, this raises an exception and crashes the program. Since
|
||||
// we usually build with exceptions turned off, what this means is that the test
|
||||
// executable will halt if the file cannot be written.
|
||||
void DumpFileSystem(const char* file_name, const StorageMap& map) {
|
||||
std::string dump = wvcdm::RebootTest::DumpData(map);
|
||||
std::ofstream output(file_name);
|
||||
output << dump;
|
||||
output.close();
|
||||
}
|
||||
|
||||
void DumpFileSystems() {
|
||||
DumpFileSystem(kGlobalDumpFileName, g_host->global_storage().files());
|
||||
DumpFileSystem(kPerOriginDumpFileName, g_host->per_origin_storage().files());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// Set up a Host and initialize the library. This makes these services
|
||||
// available to the tests. We would do this in the test suite itself, but the
|
||||
// core & OEMCrypto tests don't know they depend on this for storage.
|
||||
g_host = new TestHost();
|
||||
ReloadFileSystems();
|
||||
|
||||
// Partners will want to replace this with a real IStorage.
|
||||
Cdm::IStorage* const storage = &g_host->global_storage();
|
||||
|
||||
// Partners may also want to replace this with real implementations of IClock
|
||||
// and ITimer. If so, make not to set the command line argument
|
||||
// "--fake_sleep".
|
||||
Cdm::IClock* const clock = g_host;
|
||||
Cdm::ITimer* const timer = g_host;
|
||||
|
||||
// If the tests need a spearate file system from that used by the host, that
|
||||
// should be set up here. For the reference code, we use a default test file
|
||||
// system, but save the data from the file system.
|
||||
// A separate file system might be needed, for example, if the test data needs
|
||||
// to be saved off-device. Or, for example, if the main file system limits the
|
||||
// names and types of files it can save to certificates and offline licenses.
|
||||
wvutil::FileSystem* file_system = nullptr;
|
||||
wvcdm::RebootTest::set_file_system(file_system);
|
||||
|
||||
const int test_results = Main(storage, clock, timer, argc, argv);
|
||||
DumpFileSystems();
|
||||
// This is used by the test driver to know what time to use for initializing
|
||||
// the fake clock for the next pass.
|
||||
std::cout << "END_OF_TEST " << wvutil::Clock().GetCurrentTime() << "\n";
|
||||
return test_results;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <assert.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -10,11 +10,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#include "cdm.h"
|
||||
#include "cdm_test_runner.h"
|
||||
#include "device_cert.h"
|
||||
#include "log.h"
|
||||
#include "test_base.h"
|
||||
@@ -23,72 +20,22 @@
|
||||
using namespace widevine;
|
||||
|
||||
TestHost* g_host = nullptr;
|
||||
std::string g_sandbox_id = "";
|
||||
|
||||
namespace {
|
||||
constexpr const char kSandboxIdParam[] = "--sandbox_id=";
|
||||
|
||||
// Following the pattern established by help text in test_base.cpp
|
||||
constexpr const char kExtraHelpText[] =
|
||||
" --sandbox_id=<sandbox_id>\n"
|
||||
" Specifies the Sandbox ID that should be sent to OEMCrypto via\n"
|
||||
" OEMCrypto_SetSandbox(). On most platforms, since Sandbox IDs are not\n"
|
||||
" in use, this parameter should be omitted.\n";
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// Find and filter out the Sandbox ID, if any.
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
auto sandbox_id_iter = std::find_if(std::begin(args) + 1, std::end(args),
|
||||
[](const std::string& elem) -> bool {
|
||||
return elem.find(kSandboxIdParam) == 0;
|
||||
});
|
||||
if (sandbox_id_iter != std::end(args)) {
|
||||
g_sandbox_id = sandbox_id_iter->substr(strlen(kSandboxIdParam));
|
||||
args.erase(sandbox_id_iter);
|
||||
}
|
||||
|
||||
// Set up a Host and initialize the library. This makes these services
|
||||
// available to the tests. We would do this in the test suite itself, but the
|
||||
// core & OEMCrypto tests don't know they depend on this for storage.
|
||||
g_host = new TestHost();
|
||||
Cdm::ClientInfo client_info;
|
||||
// Set client info that denotes this as the test suite:
|
||||
client_info.product_name = "CE cdm tests";
|
||||
client_info.company_name = "www";
|
||||
client_info.model_name = "www";
|
||||
#if defined(__linux__)
|
||||
client_info.device_name = "Linux";
|
||||
{
|
||||
struct utsname name;
|
||||
if (uname(&name) == 0) {
|
||||
client_info.arch_name = name.machine;
|
||||
}
|
||||
}
|
||||
#else
|
||||
client_info.device_name = "unknown";
|
||||
#endif
|
||||
client_info.build_info = __DATE__;
|
||||
|
||||
Cdm::Status status = Cdm::initialize(
|
||||
Cdm::kNoSecureOutput, client_info, g_host, g_host, g_host,
|
||||
static_cast<Cdm::LogLevel>(wvcdm::g_cutoff), g_sandbox_id);
|
||||
(void)status; // status is now used when assertions are turned off.
|
||||
assert(status == Cdm::kSuccess);
|
||||
// TODO(b/195338975): document that using a real IStorage means you should not
|
||||
// run the tests in $CDM_DIR/cdm/test/cdm_test.cpp
|
||||
|
||||
std::vector<const char*> new_argv(args.size());
|
||||
std::transform(
|
||||
std::begin(args), std::end(args), std::begin(new_argv),
|
||||
[](const std::string& arg) -> const char* { return arg.c_str(); });
|
||||
// This must take place after the call to Cdm::initialize() because it makes
|
||||
// calls that are only valid after the library is initialized.
|
||||
if (!wvcdm::WvCdmTestBase::Initialize(new_argv.size(), new_argv.data(),
|
||||
kExtraHelpText)) {
|
||||
return 0;
|
||||
}
|
||||
// Partners will want to replace this with a real IStorage.
|
||||
Cdm::IStorage* const storage = &g_host->global_storage();
|
||||
|
||||
// Init gtest after oemcrypto and cdm host have been initialized.
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
// Partners may also want to replace this with real implementations of IClock
|
||||
// and ITimer. If so, make not to set the command line argument
|
||||
// "--fake_sleep".
|
||||
Cdm::IClock* const clock = g_host;
|
||||
Cdm::ITimer* const timer = g_host;
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
const int test_results = Main(storage, clock, timer, argc, argv);
|
||||
return test_results;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "cdm_test_printers.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
// This file adds some print methods so that when unit tests fail, the
|
||||
// will print the name of an enumeration instead of the numeric value.
|
||||
|
||||
|
||||
68
cdm/test/cdm_test_runner.cpp
Normal file
68
cdm/test/cdm_test_runner.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <assert.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "device_cert.h"
|
||||
#include "log.h"
|
||||
#include "test_base.h"
|
||||
#include "test_host.h"
|
||||
|
||||
std::string g_sandbox_id = "";
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
constexpr char kSandboxIdParam[] = "--sandbox_id=";
|
||||
|
||||
// Following the pattern established by help text in test_base.cpp
|
||||
constexpr char kExtraHelpText[] =
|
||||
" --sandbox_id=<sandbox_id>\n"
|
||||
" Specifies the Sandbox ID that should be sent to OEMCrypto via\n"
|
||||
" OEMCrypto_SetSandbox(). On most platforms, since Sandbox IDs are not\n"
|
||||
" in use, this parameter should be omitted.\n";
|
||||
} // namespace
|
||||
|
||||
int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
|
||||
int argc, char** argv) {
|
||||
// Find and filter out the Sandbox ID, if any.
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
auto sandbox_id_iter = std::find_if(std::begin(args) + 1, std::end(args),
|
||||
[](const std::string& elem) -> bool {
|
||||
return elem.find(kSandboxIdParam) == 0;
|
||||
});
|
||||
if (sandbox_id_iter != std::end(args)) {
|
||||
g_sandbox_id = sandbox_id_iter->substr(strlen(kSandboxIdParam));
|
||||
args.erase(sandbox_id_iter);
|
||||
}
|
||||
|
||||
Cdm::Status status = Cdm::initialize(
|
||||
Cdm::kOpaqueHandle, storage, clock, timer,
|
||||
static_cast<Cdm::LogLevel>(wvutil::g_cutoff), g_sandbox_id);
|
||||
(void)status; // status is now used when assertions are turned off.
|
||||
assert(status == Cdm::kSuccess);
|
||||
|
||||
std::vector<const char*> new_argv(args.size());
|
||||
std::transform(
|
||||
std::begin(args), std::end(args), std::begin(new_argv),
|
||||
[](const std::string& arg) -> const char* { return arg.c_str(); });
|
||||
// This must take place after the call to Cdm::initialize() because it makes
|
||||
// calls that are only valid after the library is initialized.
|
||||
if (!wvcdm::WvCdmTestBase::Initialize(static_cast<int>(new_argv.size()),
|
||||
new_argv.data(), kExtraHelpText)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Init gtest after oemcrypto and cdm host have been initialized.
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
} // namespace widevine
|
||||
20
cdm/test/cdm_test_runner.h
Normal file
20
cdm/test/cdm_test_runner.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
|
||||
#define WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
|
||||
|
||||
#include <iostream>
|
||||
#include "cdm.h"
|
||||
|
||||
namespace widevine {
|
||||
// Run all CDM tests using the specified storage, clock, and timer. It parses
|
||||
// standard command line arguments, sets some default test client info,
|
||||
// initializes a CDM object, and then runs all the tests.
|
||||
// Returns 0 on success.
|
||||
int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
|
||||
int argc, char** argv);
|
||||
} // namespace widevine
|
||||
|
||||
#endif // WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
|
||||
11
cdm/test/create_test_file_system.cpp
Normal file
11
cdm/test/create_test_file_system.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "create_test_file_system.h"
|
||||
|
||||
#include "test_host.h"
|
||||
|
||||
wvutil::FileSystem* CreateTestFileSystem() {
|
||||
return new wvutil::FileSystem("", &g_host->per_origin_storage());
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
//
|
||||
// This source file contains the test data used to verify decryption behavior
|
||||
// in cdm_test.cpp.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "device_cert.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef WVCDM_CDM_TEST_DEVICE_CERT_H_
|
||||
#define WVCDM_CDM_TEST_DEVICE_CERT_H_
|
||||
|
||||
14
cdm/test/dummy_app.mm
Normal file
14
cdm/test/dummy_app.mm
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
@end
|
||||
|
||||
@implementation AppDelegate {
|
||||
}
|
||||
@end
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
23
cdm/test/gtest_xctest_wrapper.mm
Normal file
23
cdm/test/gtest_xctest_wrapper.mm
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Defined in cdm_test_main.cpp.
|
||||
int main(int argc, char** argv);
|
||||
|
||||
@interface GtestTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation GtestTests
|
||||
|
||||
- (void)testAll {
|
||||
testing::GTEST_FLAG(filter) = GTEST_FILTER;
|
||||
|
||||
char arg0[] = "tests";
|
||||
char* argv[] = {arg0, nullptr};
|
||||
XCTAssertEqual(main(1, argv), 0);
|
||||
}
|
||||
|
||||
@end
|
||||
25
cdm/test/info.plist
Normal file
25
cdm/test/info.plist
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>EQHXZ8M8AV.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
/**
|
||||
The test file system for the Level 3 OEMCrypto sits on top of the host file
|
||||
system. A real production version may either use the host file system or it
|
||||
may write files directly to the file system.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
@@ -5,14 +15,17 @@
|
||||
|
||||
#include "level3_file_system_ce_test.h"
|
||||
|
||||
namespace wvoec3 {
|
||||
#include "test_host.h"
|
||||
|
||||
std::map<std::string, std::string> OEMCrypto_Level3CETestFileSystem::files_;
|
||||
namespace wvoec3 {
|
||||
|
||||
ssize_t OEMCrypto_Level3CETestFileSystem::Read(const char* filename,
|
||||
void* buffer, size_t size) {
|
||||
if (!Exists(filename)) return 0;
|
||||
std::string data = files_[std::string(filename)];
|
||||
if (!g_host) return 0;
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().exists(name)) return 0;
|
||||
std::string data;
|
||||
if (!g_host->global_storage().read(name, &data)) return 0;
|
||||
size_t bytes_read = std::min(size, data.size());
|
||||
memcpy(buffer, data.data(), bytes_read);
|
||||
return bytes_read;
|
||||
@@ -21,24 +34,31 @@ ssize_t OEMCrypto_Level3CETestFileSystem::Read(const char* filename,
|
||||
ssize_t OEMCrypto_Level3CETestFileSystem::Write(const char* filename,
|
||||
const void* buffer,
|
||||
size_t size) {
|
||||
if (!g_host) return 0;
|
||||
std::string data(static_cast<const char*>(buffer), size);
|
||||
files_[std::string(filename)] = data;
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().write(name, data)) return 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool OEMCrypto_Level3CETestFileSystem::Exists(const char* filename) {
|
||||
return files_.find(std::string(filename)) != files_.end();
|
||||
if (!g_host) return false;
|
||||
const std::string name(filename);
|
||||
return g_host->global_storage().exists(name);
|
||||
}
|
||||
|
||||
ssize_t OEMCrypto_Level3CETestFileSystem::FileSize(const char* filename) {
|
||||
if (!Exists(filename)) return -1;
|
||||
return files_[std::string(filename)].size();
|
||||
if (!g_host) return 0;
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().exists(name)) return 0;
|
||||
return static_cast<ssize_t>(g_host->global_storage().size(name));
|
||||
}
|
||||
|
||||
bool OEMCrypto_Level3CETestFileSystem::Remove(const char* filename) {
|
||||
if (!Exists(filename)) return false;
|
||||
files_.erase(std::string(filename));
|
||||
return true;
|
||||
if (!g_host) return false;
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().exists(name)) return false;
|
||||
return g_host->global_storage().remove(name);
|
||||
}
|
||||
|
||||
} // namespace wvoec3
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
/*********************************************************************
|
||||
* level3_file_system_ce_test.h
|
||||
@@ -26,9 +26,6 @@ class OEMCrypto_Level3CETestFileSystem : public OEMCrypto_Level3FileSystem {
|
||||
bool Exists(const char* filename) override;
|
||||
ssize_t FileSize(const char* filename) override;
|
||||
bool Remove(const char* filename) override;
|
||||
|
||||
private:
|
||||
static std::map<std::string, std::string> files_;
|
||||
};
|
||||
|
||||
} // namespace wvoec3
|
||||
|
||||
340
cdm/test/perf_test.cpp
Normal file
340
cdm/test/perf_test.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "perf_test.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config_test_env.h"
|
||||
#include "license_request.h"
|
||||
#include "test_host.h"
|
||||
#include "url_request.h"
|
||||
|
||||
#define ASSERT_SUCCESS(code) ASSERT_EQ(code, Cdm::kSuccess)
|
||||
#define EXPECT_SUCCESS(code) EXPECT_EQ(code, Cdm::kSuccess)
|
||||
|
||||
#define WALL_NOW std::chrono::high_resolution_clock::now()
|
||||
|
||||
TestHost* g_host = nullptr;
|
||||
|
||||
namespace widevine {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const size_t kTestCount = 50;
|
||||
|
||||
const wvcdm::ConfigTestEnv kTestData(wvcdm::kContentProtectionUatServer);
|
||||
CreateFuncType create_func = nullptr;
|
||||
|
||||
using TimeType = std::chrono::duration<double, std::milli>;
|
||||
|
||||
struct PerfInfo {
|
||||
double mean;
|
||||
double min;
|
||||
double max;
|
||||
double std_dev;
|
||||
|
||||
template <size_t Size>
|
||||
PerfInfo(const double (&values)[Size]) {
|
||||
static_assert(Size > 0, "Must pass at least one value");
|
||||
|
||||
// First pass to calculate min/max/mean.
|
||||
bool first = true;
|
||||
double sum = 0;
|
||||
for (auto v : values) {
|
||||
sum += v;
|
||||
if (first) {
|
||||
min = max = v;
|
||||
first = false;
|
||||
} else {
|
||||
if (v < min) min = v;
|
||||
if (v > max) max = v;
|
||||
}
|
||||
}
|
||||
mean = sum / Size;
|
||||
|
||||
// Second pass to calculate standard deviation.
|
||||
sum = 0;
|
||||
for (auto v : values) {
|
||||
sum += (v - mean) * (v - mean);
|
||||
}
|
||||
std_dev = std::sqrt(sum / Size);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const PerfInfo& info) {
|
||||
// mean=12.33442, std-dev=1.44421, min=1.22431, max=244.1133144
|
||||
return os << "mean=" << info.mean << ", std-dev=" << info.std_dev
|
||||
<< ", min=" << info.min << ", max=" << info.max;
|
||||
}
|
||||
|
||||
class PerfTracker {
|
||||
public:
|
||||
class Test {
|
||||
public:
|
||||
Test(PerfTracker* tracker)
|
||||
: wall_start_(WALL_NOW), cpu_start_(std::clock()), tracker_(tracker) {}
|
||||
|
||||
~Test() {
|
||||
tracker_->wall_times_[tracker_->index_] =
|
||||
TimeType(WALL_NOW - wall_start_).count();
|
||||
tracker_->cpu_times_[tracker_->index_] =
|
||||
(std::clock() - cpu_start_) * 1000.0 / CLOCKS_PER_SEC;
|
||||
tracker_->index_++;
|
||||
}
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point wall_start_;
|
||||
std::clock_t cpu_start_;
|
||||
PerfTracker* tracker_;
|
||||
};
|
||||
|
||||
void Print(const std::string& name, size_t block_size_bytes = 0) {
|
||||
PerfInfo wall_perf(wall_times_);
|
||||
PerfInfo cpu_perf(cpu_times_);
|
||||
std::cout << name << " (wall, ms): " << wall_perf << "\n";
|
||||
std::cout << name << " (cpu, ms): " << cpu_perf << "\n";
|
||||
if (block_size_bytes) {
|
||||
// |mean| is in milliseconds.
|
||||
std::cout << name << " (wall, MBit/sec): "
|
||||
<< (block_size_bytes * 8 * 1000 / wall_perf.mean / 1024 / 1024)
|
||||
<< "\n";
|
||||
std::cout << name << " (cpu, MBit/sec): "
|
||||
<< (block_size_bytes * 8 * 1000 / cpu_perf.mean / 1024 / 1024)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
double wall_times_[kTestCount];
|
||||
double cpu_times_[kTestCount];
|
||||
size_t index_ = 0;
|
||||
};
|
||||
|
||||
#define MEASURE_PERF(tracker, code) \
|
||||
{ \
|
||||
PerfTracker::Test test(&(tracker)); \
|
||||
code; \
|
||||
}
|
||||
|
||||
class EventListener : public Cdm::IEventListener {
|
||||
public:
|
||||
struct MessageInfo {
|
||||
std::string session_id;
|
||||
std::string message;
|
||||
Cdm::MessageType message_type;
|
||||
};
|
||||
|
||||
void onMessage(const std::string& session_id, Cdm::MessageType message_type,
|
||||
const std::string& message) override {
|
||||
messages.push_back({session_id, message, message_type});
|
||||
}
|
||||
void onKeyStatusesChange(const std::string& session_id,
|
||||
bool has_new_usable_key) override {}
|
||||
void onRemoveComplete(const std::string& session_id) override {}
|
||||
|
||||
std::vector<MessageInfo> messages;
|
||||
};
|
||||
|
||||
bool SendPost(const std::string& message, std::string* response) {
|
||||
wvcdm::UrlRequest req(kTestData.license_server());
|
||||
std::string raw_response;
|
||||
if (!req.is_connected() || !req.PostRequest(message) ||
|
||||
!req.GetResponse(&raw_response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wvcdm::LicenseRequest helper;
|
||||
helper.GetDrmMessage(raw_response, *response);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Cdm> CreateCdm(EventListener* event_listener) {
|
||||
std::unique_ptr<Cdm> ret(
|
||||
create_func(event_listener, &g_host->per_origin_storage(), true));
|
||||
if (ret) {
|
||||
EXPECT_SUCCESS(ret->setServiceCertificate(
|
||||
Cdm::kProvisioningService,
|
||||
kTestData.provisioning_service_certificate()));
|
||||
EXPECT_SUCCESS(ret->setServiceCertificate(
|
||||
Cdm::kLicensingService, kTestData.license_service_certificate()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
class GlobalEnv : public testing::Environment {
|
||||
public:
|
||||
GlobalEnv(InitFuncType init_func, const std::string& cert)
|
||||
: init_func_(init_func), cert_(cert) {}
|
||||
|
||||
void SetUp() override {
|
||||
g_host = new TestHost;
|
||||
if (!cert_.empty()) g_host->per_origin_storage().write("cert.bin", cert_);
|
||||
|
||||
Cdm::LogLevel log_level = Cdm::kErrors;
|
||||
if (const char* verbose = getenv("VERBOSE_OUTPUT")) {
|
||||
if (std::strcmp(verbose, "1") == 0) log_level = Cdm::kVerbose;
|
||||
}
|
||||
ASSERT_SUCCESS(init_func_(Cdm::kNoSecureOutput, &g_host->global_storage(),
|
||||
g_host, g_host, log_level));
|
||||
}
|
||||
|
||||
private:
|
||||
const InitFuncType init_func_;
|
||||
const std::string cert_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class PerfTest : public testing::Test {};
|
||||
|
||||
TEST_F(PerfTest, LicenseExchange) {
|
||||
EventListener event_listener;
|
||||
auto cdm = CreateCdm(&event_listener);
|
||||
ASSERT_TRUE(cdm);
|
||||
ASSERT_EQ(cdm->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
PerfTracker create;
|
||||
PerfTracker generate;
|
||||
PerfTracker update;
|
||||
PerfTracker close;
|
||||
for (size_t i = 0; i < kTestCount; i++) {
|
||||
std::string session_id;
|
||||
MEASURE_PERF(create, ASSERT_SUCCESS(
|
||||
cdm->createSession(Cdm::kTemporary, &session_id)));
|
||||
|
||||
MEASURE_PERF(
|
||||
generate,
|
||||
ASSERT_SUCCESS(cdm->generateRequest(
|
||||
session_id, Cdm::kCenc,
|
||||
wvcdm::ConfigTestEnv::GetInitData(wvcdm::kContentIdStreaming))));
|
||||
|
||||
std::string response;
|
||||
ASSERT_TRUE(SendPost(event_listener.messages[0].message, &response));
|
||||
|
||||
MEASURE_PERF(update, ASSERT_SUCCESS(cdm->update(session_id, response)));
|
||||
|
||||
MEASURE_PERF(close, ASSERT_SUCCESS(cdm->close(session_id)));
|
||||
|
||||
event_listener.messages.pop_back();
|
||||
}
|
||||
|
||||
create.Print("Create ");
|
||||
generate.Print("Generate");
|
||||
update.Print("Update ");
|
||||
close.Print("Close ");
|
||||
}
|
||||
|
||||
class DecryptPerfTest : public PerfTest,
|
||||
public testing::WithParamInterface<bool> {};
|
||||
|
||||
TEST_P(DecryptPerfTest, Decrypt) {
|
||||
EventListener event_listener;
|
||||
auto cdm = CreateCdm(&event_listener);
|
||||
ASSERT_TRUE(cdm);
|
||||
ASSERT_EQ(cdm->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
std::string session_id;
|
||||
ASSERT_SUCCESS(cdm->createSession(Cdm::kTemporary, &session_id));
|
||||
ASSERT_SUCCESS(cdm->generateRequest(
|
||||
session_id, Cdm::kCenc,
|
||||
wvcdm::ConfigTestEnv::GetInitData(wvcdm::kContentIdStreaming)));
|
||||
|
||||
std::string response;
|
||||
ASSERT_TRUE(SendPost(event_listener.messages[0].message, &response));
|
||||
ASSERT_SUCCESS(cdm->update(session_id, response));
|
||||
|
||||
Cdm::KeyStatusMap statuses;
|
||||
ASSERT_SUCCESS(cdm->getKeyStatuses(session_id, &statuses));
|
||||
ASSERT_GT(statuses.size(), 0u);
|
||||
const std::string key_id = statuses.begin()->first;
|
||||
|
||||
// Use in-place decrypt to avoid allocations. We don't care about the data,
|
||||
// so we can just decrypt the same buffer again.
|
||||
constexpr const size_t k16M = 16 * 1024 * 1024;
|
||||
std::vector<uint8_t> buffer(k16M);
|
||||
uint8_t iv[16];
|
||||
for (auto& b : buffer) b = rand();
|
||||
|
||||
Cdm::DecryptionBatch batch;
|
||||
batch.key_id = reinterpret_cast<const uint8_t*>(key_id.data());
|
||||
batch.key_id_length = static_cast<uint32_t>(key_id.size());
|
||||
if (GetParam()) {
|
||||
batch.pattern.encrypted_blocks = batch.pattern.clear_blocks = 0;
|
||||
} else {
|
||||
batch.pattern.encrypted_blocks = 1;
|
||||
batch.pattern.clear_blocks = 9;
|
||||
}
|
||||
batch.is_secure = false;
|
||||
batch.encryption_scheme = GetParam() ? Cdm::kAesCtr : Cdm::kAesCbc;
|
||||
batch.is_video = true;
|
||||
|
||||
Cdm::Subsample subsample;
|
||||
subsample.clear_bytes = 0;
|
||||
// subsample.encrypted_bytes set in the test.
|
||||
Cdm::Sample sample;
|
||||
sample.input.iv = iv;
|
||||
sample.input.iv_length = 16;
|
||||
sample.input.data = buffer.data();
|
||||
// sample.data_length set in the test.
|
||||
sample.input.subsamples = &subsample;
|
||||
sample.input.subsamples_length = 1;
|
||||
sample.output.data = buffer.data();
|
||||
sample.output.data_offset = 0;
|
||||
sample.output.data_length = static_cast<uint32_t>(buffer.size());
|
||||
batch.samples = &sample;
|
||||
batch.samples_length = 1;
|
||||
|
||||
constexpr const size_t block_sizes[] = {8 * 1024, 256 * 1024, k16M};
|
||||
constexpr const size_t sizes_count =
|
||||
sizeof(block_sizes) / sizeof(block_sizes[0]);
|
||||
const std::string block_names[] = {" 8k", "256k", " 16M"};
|
||||
PerfTracker perf[sizes_count];
|
||||
for (size_t i = 0; i < sizes_count; i++) {
|
||||
subsample.protected_bytes = sample.input.data_length =
|
||||
sample.output.data_length = static_cast<uint32_t>(block_sizes[i]);
|
||||
for (size_t j = 0; j < kTestCount; j++) {
|
||||
MEASURE_PERF(perf[i], ASSERT_SUCCESS(cdm->decrypt(batch)));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizes_count; i++) {
|
||||
perf[i].Print("Decrypt " + block_names[i], block_sizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string PrintDecryptParam(const testing::TestParamInfo<bool>& info) {
|
||||
return info.param ? "CTR" : "CBC";
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(Decrypt, DecryptPerfTest, testing::Bool(),
|
||||
PrintDecryptParam);
|
||||
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create,
|
||||
const std::string& cert) {
|
||||
#ifdef _DEBUG
|
||||
// Don't use #error since we build all targets and we don't want to fail the
|
||||
// debug build (and we can't have configuration-specific targets).
|
||||
fprintf(stderr, "Don't run performance tests in Debug mode\n");
|
||||
return 1;
|
||||
#else
|
||||
create_func = create;
|
||||
testing::AddGlobalTestEnvironment(new GlobalEnv(init_func, cert));
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
23
cdm/test/perf_test.h
Normal file
23
cdm/test/perf_test.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef WVCDM_CDM_TEST_PERF_TEST_H_
|
||||
#define WVCDM_CDM_TEST_PERF_TEST_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cdm.h"
|
||||
|
||||
namespace widevine {
|
||||
|
||||
using InitFuncType = Cdm::Status (*)(Cdm::SecureOutputType, Cdm::IStorage*,
|
||||
Cdm::IClock*, Cdm::ITimer*, Cdm::LogLevel);
|
||||
using CreateFuncType = Cdm* (*)(Cdm::IEventListener*, Cdm::IStorage*, bool);
|
||||
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create_func,
|
||||
const std::string& cert);
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
#endif // WVCDM_CDM_TEST_PERF_TEST_H_
|
||||
84
cdm/test/perf_test_dynamic.cpp
Normal file
84
cdm/test/perf_test_dynamic.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
// This uses dlopen() which is only usable on POSIX platforms. The function
|
||||
// names assume GCC/Clang.
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <tuple>
|
||||
|
||||
#include "clock.h"
|
||||
#include "perf_test.h"
|
||||
#include "test_host.h"
|
||||
|
||||
namespace widevine {
|
||||
|
||||
constexpr char kInitName[] =
|
||||
"_ZN8widevine3Cdm10initializeENS0_16SecureOutputTypeEPNS0_8IStorageEPNS0_"
|
||||
"6IClockEPNS0_6ITimerENS0_8LogLevelE";
|
||||
constexpr char kCreateName[] =
|
||||
"_ZN8widevine3Cdm6createEPNS0_14IEventListenerEPNS0_8IStorageEb";
|
||||
|
||||
bool ReadFile(const std::string& path, std::string* output) {
|
||||
constexpr size_t kReadSize = 8 * 1024;
|
||||
std::ifstream fs(path, std::ios::in | std::ios::binary);
|
||||
if (!fs) return false;
|
||||
while (true) {
|
||||
const size_t offset = output->size();
|
||||
output->resize(output->size() + kReadSize);
|
||||
fs.read(&output->at(offset), kReadSize);
|
||||
if (fs.eof()) {
|
||||
output->resize(offset + fs.gcount());
|
||||
return true;
|
||||
} else if (!fs) {
|
||||
fprintf(stderr, "Error reading from cert file\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<InitFuncType, CreateFuncType> LoadCdm(const char* path) {
|
||||
// Note we will leak the library object; but this is just for tests and will
|
||||
// be unloaded when we exit anyway.
|
||||
auto dll = dlopen(path, RTLD_NOW);
|
||||
if (!dll) {
|
||||
fprintf(stderr, "Error loading so file: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
auto init = reinterpret_cast<InitFuncType>(dlsym(dll, kInitName));
|
||||
auto create = reinterpret_cast<CreateFuncType>(dlsym(dll, kCreateName));
|
||||
if (!init || !create) {
|
||||
fprintf(stderr, "Error finding CDM functions: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
return std::make_tuple(init, create);
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
namespace wvutil {
|
||||
|
||||
int64_t Clock::GetCurrentTime() { return g_host->now() / 1000; }
|
||||
|
||||
} // namespace wvutil
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <CDM_SO_PATH> <CERT_PATH>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string cert;
|
||||
if (!widevine::ReadFile(argv[2], &cert))
|
||||
return 1;
|
||||
|
||||
auto funcs = widevine::LoadCdm(argv[1]);
|
||||
return widevine::PerfTestMain(std::get<0>(funcs), std::get<1>(funcs), cert);
|
||||
}
|
||||
29
cdm/test/perf_test_xctest.mm
Normal file
29
cdm/test/perf_test_xctest.mm
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "device_cert.h"
|
||||
#include "perf_test.h"
|
||||
|
||||
@interface GtestTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation GtestTests
|
||||
|
||||
- (void)testAll {
|
||||
testing::GTEST_FLAG(filter) = GTEST_FILTER;
|
||||
char arg0[] = "tests";
|
||||
char* argv[] = {arg0, nullptr};
|
||||
int argc = 1;
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
std::string cert{kDeviceCert, kDeviceCert + kDeviceCertSize};
|
||||
printf("Size 1: %zu, 2: %zu\n", kDeviceCertSize, cert.size());
|
||||
XCTAssertEqual(widevine::PerfTestMain(&widevine::Cdm::initialize, &widevine::Cdm::create, cert), 0);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,12 +1,15 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#include "test_host.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <chrono>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "cdm_version.h"
|
||||
#include "device_cert.h"
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
|
||||
using namespace widevine;
|
||||
@@ -15,28 +18,40 @@ namespace {
|
||||
|
||||
constexpr char kCertificateFilename[] = "cert.bin";
|
||||
|
||||
// Some files are expected to go in global storage. All other files are expected
|
||||
// to go in per-origin storage. To help us enforce this in tests, this set
|
||||
// tracks the filenames that belong in global storage. TestHost::Storage will
|
||||
// reject attempts to access these files via per-origin storage or to access
|
||||
// files not in this list via global storage.
|
||||
const std::unordered_set<std::string> kGlobalFilenames = {
|
||||
"usgtable.bin",
|
||||
"StoredUsageTime.dat",
|
||||
"GenerationNumber.dat",
|
||||
"persistent.dat",
|
||||
"okp.bin",
|
||||
"keybox.dat",
|
||||
wvutil::kOemCertificateFileName,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TestHost::TestHost() { Reset(); }
|
||||
TestHost::~TestHost() { wvcdm::TestSleep::set_callback(nullptr); }
|
||||
TestHost::TestHost() : global_storage_(true), per_origin_storage_(false) {
|
||||
Reset();
|
||||
}
|
||||
TestHost::~TestHost() { wvutil::TestSleep::set_callback(nullptr); }
|
||||
|
||||
void TestHost::Reset() {
|
||||
auto now = std::chrono::steady_clock().now();
|
||||
auto now = std::chrono::system_clock().now();
|
||||
now_ = now.time_since_epoch() / std::chrono::milliseconds(1);
|
||||
wvcdm::TestSleep::set_callback(this);
|
||||
|
||||
save_device_cert_ = false;
|
||||
wvutil::TestSleep::set_callback(this);
|
||||
|
||||
// Surprisingly, std::priority_queue has no clear().
|
||||
while (!timers_.empty()) {
|
||||
timers_.pop();
|
||||
}
|
||||
|
||||
files_.clear();
|
||||
files_[kCertificateFilename] =
|
||||
(device_cert_.size() > 0)
|
||||
? device_cert_
|
||||
: std::string((const char*)kDeviceCert, kDeviceCertSize);
|
||||
global_storage_.Reset();
|
||||
per_origin_storage_.Reset();
|
||||
}
|
||||
|
||||
void TestHost::ElapseTime(int64_t milliseconds) {
|
||||
@@ -64,58 +79,7 @@ void TestHost::ElapseTime(int64_t milliseconds) {
|
||||
now_ = goal_time;
|
||||
}
|
||||
|
||||
int TestHost::NumTimers() const { return timers_.size(); }
|
||||
|
||||
bool TestHost::read(const std::string& name, std::string* data) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("read file: %s: %s", name.c_str(), ok ? "ok" : "fail");
|
||||
if (!ok) return false;
|
||||
*data = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::write(const std::string& name, const std::string& data) {
|
||||
LOGV("write file: %s", name.c_str());
|
||||
files_[name] = data;
|
||||
if (save_device_cert_ && name.compare(kCertificateFilename) == 0) {
|
||||
device_cert_ = data;
|
||||
save_device_cert_ = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::exists(const std::string& name) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("exists? %s: %s", name.c_str(), ok ? "true" : "false");
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool TestHost::remove(const std::string& name) {
|
||||
LOGV("remove: %s", name.c_str());
|
||||
if (name.empty()) {
|
||||
// If no name, delete all files (see DeviceFiles::DeleteAllFiles())
|
||||
files_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return files_.erase(name) > 0;
|
||||
}
|
||||
|
||||
int32_t TestHost::size(const std::string& name) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
if (it == files_.end()) return -1;
|
||||
return it->second.size();
|
||||
}
|
||||
|
||||
bool TestHost::list(std::vector<std::string>* names) {
|
||||
names->clear();
|
||||
for (StorageMap::iterator it = files_.begin(); it != files_.end(); it++) {
|
||||
names->push_back(it->first);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
size_t TestHost::NumTimers() const { return timers_.size(); }
|
||||
|
||||
int64_t TestHost::now() { return now_; }
|
||||
|
||||
@@ -140,3 +104,77 @@ void TestHost::cancel(IClient* client) {
|
||||
// Now swap the queues.
|
||||
std::swap(timers_, others);
|
||||
}
|
||||
|
||||
TestHost::Storage::Storage(bool is_global) : is_global_(is_global) { Reset(); }
|
||||
|
||||
void TestHost::Storage::Reset() {
|
||||
files_.clear();
|
||||
if (!is_global_) {
|
||||
files_[kCertificateFilename] =
|
||||
std::string((const char*)kDeviceCert, kDeviceCertSize);
|
||||
}
|
||||
}
|
||||
|
||||
bool TestHost::Storage::read(const std::string& name, std::string* data) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("read file: %s: %s", name.c_str(), ok ? "ok" : "fail");
|
||||
if (!CheckFilename(name) || !ok) return false;
|
||||
*data = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::write(const std::string& name,
|
||||
const std::string& data) {
|
||||
LOGV("write file: %s", name.c_str());
|
||||
if (!CheckFilename(name)) return false;
|
||||
files_[name] = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::exists(const std::string& name) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("exists? %s: %s", name.c_str(), ok ? "true" : "false");
|
||||
if (!CheckFilename(name)) return false;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::remove(const std::string& name) {
|
||||
if (name.empty()) {
|
||||
// If no name, delete all files (see DeviceFiles::DeleteAllFiles())
|
||||
LOGV("remove all files");
|
||||
files_.clear();
|
||||
return true;
|
||||
}
|
||||
LOGV("remove: %s", name.c_str());
|
||||
if (!CheckFilename(name)) return false;
|
||||
return files_.erase(name) > 0;
|
||||
}
|
||||
|
||||
int32_t TestHost::Storage::size(const std::string& name) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = (it != files_.end());
|
||||
LOGV("size? %s: %s", name.c_str(), ok ? "ok" : "fail");
|
||||
if (!CheckFilename(name) || !ok) return -1;
|
||||
return static_cast<int32_t>(it->second.size());
|
||||
}
|
||||
|
||||
bool TestHost::Storage::list(std::vector<std::string>* names) {
|
||||
names->clear();
|
||||
for (StorageMap::iterator it = files_.begin(); it != files_.end(); it++) {
|
||||
names->push_back(it->first);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::CheckFilename(const std::string& name) {
|
||||
const bool is_global_filename =
|
||||
(kGlobalFilenames.find(name) != kGlobalFilenames.end());
|
||||
if (is_global_ != is_global_filename) {
|
||||
LOGE("Attempt to access %s in %s storage rejected.", name.c_str(),
|
||||
is_global_ ? "global" : "per-origin");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#ifndef WVCDM_CDM_TEST_TEST_HOST_H_
|
||||
#define WVCDM_CDM_TEST_TEST_HOST_H_
|
||||
|
||||
@@ -15,30 +15,47 @@
|
||||
// This provides a host environment for running CDM tests. It implements the
|
||||
// IStorage, IClock and ITimer interfaces that a host would normally implement,
|
||||
// while allowing them to be manipulated by the test.
|
||||
class TestHost : public widevine::Cdm::IStorage,
|
||||
public widevine::Cdm::IClock,
|
||||
class TestHost : public widevine::Cdm::IClock,
|
||||
public widevine::Cdm::ITimer,
|
||||
public wvcdm::TestSleep::CallBack {
|
||||
public wvutil::TestSleep::CallBack {
|
||||
public:
|
||||
class Storage : public widevine::Cdm::IStorage {
|
||||
public:
|
||||
typedef std::map<std::string, std::string> StorageMap;
|
||||
|
||||
explicit Storage(bool is_global);
|
||||
~Storage() override {}
|
||||
void Reset();
|
||||
|
||||
// Reset the file system to contain the specified files.
|
||||
void ResetFiles(const StorageMap& files) { files_ = files; };
|
||||
const StorageMap& files() const { return files_; }
|
||||
|
||||
// widevine::Cdm::IStorage
|
||||
bool read(const std::string& name, std::string* data) override;
|
||||
bool write(const std::string& name, const std::string& data) override;
|
||||
bool exists(const std::string& name) override;
|
||||
bool remove(const std::string& name) override;
|
||||
int32_t size(const std::string& name) override;
|
||||
bool list(std::vector<std::string>* names) override;
|
||||
|
||||
private:
|
||||
bool is_global_;
|
||||
StorageMap files_;
|
||||
|
||||
bool CheckFilename(const std::string& name);
|
||||
};
|
||||
|
||||
TestHost();
|
||||
~TestHost();
|
||||
~TestHost() override;
|
||||
void Reset();
|
||||
|
||||
// Used for manipulating and inspecting timer states during testing.
|
||||
void ElapseTime(int64_t milliseconds) override;
|
||||
int NumTimers() const;
|
||||
size_t NumTimers() const;
|
||||
|
||||
// This should be called before trying to write the cert.bin file. This is
|
||||
// used when testing device provisioning.
|
||||
void SaveProvisioningInformation() { save_device_cert_ = true; }
|
||||
|
||||
// widevine::Cdm::IStorage
|
||||
bool read(const std::string& name, std::string* data) override;
|
||||
bool write(const std::string& name, const std::string& data) override;
|
||||
bool exists(const std::string& name) override;
|
||||
bool remove(const std::string& name) override;
|
||||
int32_t size(const std::string& name) override;
|
||||
bool list(std::vector<std::string>* names) override;
|
||||
Storage& global_storage() { return global_storage_; }
|
||||
Storage& per_origin_storage() { return per_origin_storage_; }
|
||||
|
||||
// widevine::Cdm::IClock
|
||||
int64_t now() override;
|
||||
@@ -71,11 +88,8 @@ class TestHost : public widevine::Cdm::IStorage,
|
||||
int64_t now_;
|
||||
std::priority_queue<Timer> timers_;
|
||||
|
||||
std::string device_cert_;
|
||||
bool save_device_cert_;
|
||||
|
||||
typedef std::map<std::string, std::string> StorageMap;
|
||||
StorageMap files_;
|
||||
Storage global_storage_;
|
||||
Storage per_origin_storage_;
|
||||
};
|
||||
|
||||
// Owned and managed by the test runner.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine Master License
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
{
|
||||
'variables': {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
# source code may only be used and distributed under the Widevine Master License
|
||||
# source code may only be used and distributed under the Widevine License
|
||||
# Agreement.
|
||||
{
|
||||
'sources': [
|
||||
'../util/test/base64_test.cpp',
|
||||
'../util/test/cdm_random_unittest.cpp',
|
||||
# TODO(b/119200528): Needs test vectors
|
||||
# TODO(b/167126046): Needs test vectors
|
||||
# '../util/test/file_store_unittest.cpp',
|
||||
],
|
||||
'include_dirs': [
|
||||
|
||||
Reference in New Issue
Block a user