Refactor file_store to use smart pointers
Bug: b/119276649 Merge from: http://go/wvgerrit/66367 Test: Android, CE CDM, Linux unit tests The FileSystem interface as it exists expects an Open for a file and then a Close when finished. However, the Close doesn't delete the file itself and depending on the platform, the underlying impl_ as well, leading to a memory leak. To fix this leak as well as harden against future memory issues, this change refactors the interface to shift away from raw pointers and towards smart pointers. Change-Id: I7a7132ea95cd3775796a540f510b698f4f27dd24
This commit is contained in:
@@ -1152,7 +1152,7 @@ bool DeviceFiles::StoreFileRaw(const std::string& name,
|
||||
|
||||
path += name;
|
||||
|
||||
File* file =
|
||||
auto file =
|
||||
file_system_->Open(path, FileSystem::kCreate | FileSystem::kTruncate);
|
||||
if (!file) {
|
||||
LOGW("DeviceFiles::StoreFileRaw: File open failed: %s", path.c_str());
|
||||
@@ -1160,7 +1160,6 @@ bool DeviceFiles::StoreFileRaw(const std::string& name,
|
||||
}
|
||||
|
||||
ssize_t bytes = file->Write(serialized_file.data(), serialized_file.size());
|
||||
file->Close();
|
||||
|
||||
if (bytes != static_cast<ssize_t>(serialized_file.size())) {
|
||||
LOGW(
|
||||
@@ -1208,7 +1207,7 @@ bool DeviceFiles::RetrieveHashedFile(
|
||||
return false;
|
||||
}
|
||||
|
||||
File* file = file_system_->Open(path, FileSystem::kReadOnly);
|
||||
auto file = file_system_->Open(path, FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
@@ -1216,7 +1215,6 @@ bool DeviceFiles::RetrieveHashedFile(
|
||||
std::string serialized_hash_file;
|
||||
serialized_hash_file.resize(bytes);
|
||||
bytes = file->Read(&serialized_hash_file[0], serialized_hash_file.size());
|
||||
file->Close();
|
||||
|
||||
if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) {
|
||||
LOGW("DeviceFiles::RetrieveHashedFile: read failed");
|
||||
|
||||
@@ -436,12 +436,11 @@ class WatchDog {
|
||||
wvcdm::FileSystem file_system;
|
||||
std::string filename = FailureFilename();
|
||||
if (!file_system.Exists(filename)) return;
|
||||
wvcdm::File* file = file_system.Open(filename, file_system.kReadOnly);
|
||||
auto file = file_system.Open(filename, file_system.kReadOnly);
|
||||
if (file) {
|
||||
uint32_t flag = 0;
|
||||
ssize_t size = sizeof(flag);
|
||||
ssize_t size_read = file->Read(reinterpret_cast<char*>(&flag), size);
|
||||
file->Close();
|
||||
file_system.Remove(filename);
|
||||
if (size == size_read && flag) {
|
||||
LOGE("Previous L3 Init failed.");
|
||||
@@ -457,8 +456,8 @@ class WatchDog {
|
||||
wvcdm::FileSystem file_system;
|
||||
std::string filename = FailureFilename();
|
||||
LOGD("failure filename = %s", filename.c_str());
|
||||
wvcdm::File* file = file_system.Open(
|
||||
filename, file_system.kCreate | file_system.kTruncate);
|
||||
auto file =
|
||||
file_system.Open(filename, file_system.kCreate | file_system.kTruncate);
|
||||
if (!file) {
|
||||
LOGE("Could not create file %s", filename.c_str());
|
||||
return;
|
||||
@@ -466,7 +465,6 @@ class WatchDog {
|
||||
uint32_t flag = 0x6261640a; // bad
|
||||
ssize_t size = sizeof(flag);
|
||||
ssize_t size_written = file->Write(reinterpret_cast<char*>(&flag), size);
|
||||
file->Close();
|
||||
if (size != size_written) {
|
||||
LOGE("Wrote %d bytes, not %d, to file %s", size_written, size,
|
||||
filename.c_str());
|
||||
@@ -823,7 +821,7 @@ class Adapter {
|
||||
OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX);
|
||||
return false;
|
||||
}
|
||||
wvcdm::File* file = file_system.Open(filename, file_system.kReadOnly);
|
||||
auto file = file_system.Open(filename, file_system.kReadOnly);
|
||||
if (!file) {
|
||||
// A keybox or cert file was found, but can't open it. Give up.
|
||||
LOGW("Could not open %s. Falling Back to L3.", filename.c_str());
|
||||
@@ -835,7 +833,6 @@ class Adapter {
|
||||
}
|
||||
std::vector<uint8_t> root_key(size);
|
||||
ssize_t size_read = file->Read(reinterpret_cast<char*>(&root_key[0]), size);
|
||||
file->Close();
|
||||
if (level1_.InstallKeyboxOrOEMCert(&root_key[0], size_read) !=
|
||||
OEMCrypto_SUCCESS) {
|
||||
// A keybox or cert file was read, but I could not install it. Give up.
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include <string>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "properties.h"
|
||||
@@ -1955,12 +1957,11 @@ UsageTableTestInfo kUsageTableInfoTestData[] = {
|
||||
|
||||
class MockFile : public File {
|
||||
public:
|
||||
MockFile() : File(NULL) {}
|
||||
~MockFile() {}
|
||||
MockFile() {}
|
||||
~MockFile() override {}
|
||||
|
||||
MOCK_METHOD2(Read, ssize_t(char*, size_t));
|
||||
MOCK_METHOD2(Write, ssize_t(const char*, size_t));
|
||||
MOCK_METHOD0(Close, void());
|
||||
};
|
||||
|
||||
class MockFileSystem : public FileSystem {
|
||||
@@ -1968,7 +1969,15 @@ class MockFileSystem : public FileSystem {
|
||||
MockFileSystem() {}
|
||||
~MockFileSystem() {}
|
||||
|
||||
MOCK_METHOD2(Open, File*(const std::string&, int flags));
|
||||
// Until gmock is updated to a version post-April 2017, we need this
|
||||
// workaround to test functions that take or return smart pointers.
|
||||
// See
|
||||
// https://github.com/abseil/googletest/blob/master/googlemock/docs/CookBook.md#legacy-workarounds-for-move-only-types
|
||||
std::unique_ptr<File> Open(const std::string& buffer, int flags) {
|
||||
return std::unique_ptr<File>(DoOpen(buffer, flags));
|
||||
}
|
||||
|
||||
MOCK_METHOD2(DoOpen, File*(const std::string&, int flags));
|
||||
MOCK_METHOD0(IsFactoryReset, bool());
|
||||
|
||||
MOCK_METHOD1(Exists, bool(const std::string&));
|
||||
@@ -1982,10 +1991,12 @@ class MockFileSystem : public FileSystem {
|
||||
// gmock methods
|
||||
using ::testing::_;
|
||||
using ::testing::AllOf;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::Eq;
|
||||
using ::testing::Gt;
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::InvokeWithoutArgs;
|
||||
using ::testing::NotNull;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnArg;
|
||||
@@ -2085,8 +2096,9 @@ MATCHER_P(ContainsAllElementsInVector, str_vector, "") {
|
||||
std::string data(arg, str_length + kProtobufEstimatedOverhead);
|
||||
bool all_entries_found = true;
|
||||
for (size_t i = 0; i < str_vector.size(); ++i) {
|
||||
if (data.find(str_vector[i]) == std::string::npos)
|
||||
if (data.find(str_vector[i]) == std::string::npos) {
|
||||
all_entries_found = false;
|
||||
}
|
||||
}
|
||||
return all_entries_found;
|
||||
}
|
||||
@@ -2159,15 +2171,15 @@ TEST_F(DeviceCertificateStoreTest, StoreCertificate) {
|
||||
std::string device_certificate_path =
|
||||
device_base_path_ + DeviceFiles::GetCertificateFileName();
|
||||
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system,
|
||||
Open(StrEq(device_certificate_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Write(Contains(certificate, wrapped_private_key, 0),
|
||||
Gt(certificate.size() + wrapped_private_key.size())))
|
||||
DoOpen(StrEq(device_certificate_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Write(Contains(certificate, wrapped_private_key, 0),
|
||||
Gt(certificate.size() + wrapped_private_key.size())))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(file, Read(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2181,18 +2193,18 @@ TEST_F(DeviceCertificateTest, DISABLED_ReadCertificate) {
|
||||
device_base_path_ + DeviceFiles::GetCertificateFileName();
|
||||
std::string data = a2bs_hex(kTestCertificateFileData);
|
||||
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path)))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path)))
|
||||
.WillOnce(Return(data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(device_certificate_path), _))
|
||||
.WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(data.size())))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(device_certificate_path), _))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
|
||||
Return(data.size())));
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(file, Write(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Write(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2215,7 +2227,7 @@ TEST_F(DeviceCertificateTest, HasCertificate) {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path)))
|
||||
.WillOnce(Return(false))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(file_system, Open(_, _)).Times(0);
|
||||
EXPECT_CALL(file_system, DoOpen(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
ASSERT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2238,15 +2250,15 @@ TEST_P(DeviceFilesSecurityLevelTest, SecurityLevel) {
|
||||
std::string device_certificate_path =
|
||||
device_base_path + DeviceFiles::GetCertificateFileName();
|
||||
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system,
|
||||
Open(StrEq(device_certificate_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Write(Contains(certificate, wrapped_private_key, 0),
|
||||
Gt(certificate.size() + wrapped_private_key.size())))
|
||||
DoOpen(StrEq(device_certificate_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Write(Contains(certificate, wrapped_private_key, 0),
|
||||
Gt(certificate.size() + wrapped_private_key.size())))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(file, Read(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(security_level));
|
||||
@@ -2266,22 +2278,22 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) {
|
||||
CdmAppParameterMap app_parameters =
|
||||
GetAppParameters(license_test_data[license_num].app_parameters);
|
||||
|
||||
MockFile file;
|
||||
EXPECT_CALL(file_system, Open(StrEq(license_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(&file));
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(license_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(
|
||||
file, Write(Contains(license_test_data[license_num].pssh_data,
|
||||
license_test_data[license_num].key_request,
|
||||
license_test_data[license_num].key_response,
|
||||
license_test_data[license_num].key_renewal_request,
|
||||
license_test_data[license_num].key_renewal_response,
|
||||
license_test_data[license_num].key_release_url,
|
||||
app_parameters,
|
||||
license_test_data[license_num].usage_entry),
|
||||
Gt(GetLicenseDataSize(license_test_data[license_num]))))
|
||||
*file, Write(Contains(license_test_data[license_num].pssh_data,
|
||||
license_test_data[license_num].key_request,
|
||||
license_test_data[license_num].key_response,
|
||||
license_test_data[license_num].key_renewal_request,
|
||||
license_test_data[license_num].key_renewal_response,
|
||||
license_test_data[license_num].key_release_url,
|
||||
app_parameters,
|
||||
license_test_data[license_num].usage_entry),
|
||||
Gt(GetLicenseDataSize(license_test_data[license_num]))))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(file, Read(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2305,7 +2317,6 @@ INSTANTIATE_TEST_CASE_P(StoreLicense, DeviceFilesStoreTest, ::testing::Bool());
|
||||
|
||||
TEST_F(DeviceFilesTest, StoreLicenses) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
for (size_t i = 0; i < kNumberOfLicenses; ++i) {
|
||||
std::string license_path = device_base_path_ +
|
||||
@@ -2315,22 +2326,23 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
|
||||
CdmAppParameterMap app_parameters =
|
||||
GetAppParameters(license_test_data[i].app_parameters);
|
||||
|
||||
EXPECT_CALL(file_system, Open(StrEq(license_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(&file));
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(license_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(file));
|
||||
|
||||
EXPECT_CALL(file, Write(Contains(license_test_data[i].pssh_data,
|
||||
license_test_data[i].key_request,
|
||||
license_test_data[i].key_response,
|
||||
license_test_data[i].key_renewal_request,
|
||||
license_test_data[i].key_renewal_response,
|
||||
license_test_data[i].key_release_url,
|
||||
app_parameters,
|
||||
license_test_data[i].usage_entry),
|
||||
Gt(GetLicenseDataSize(license_test_data[i]))))
|
||||
EXPECT_CALL(
|
||||
*file, Write(Contains(license_test_data[i].pssh_data,
|
||||
license_test_data[i].key_request,
|
||||
license_test_data[i].key_response,
|
||||
license_test_data[i].key_renewal_request,
|
||||
license_test_data[i].key_renewal_response,
|
||||
license_test_data[i].key_release_url,
|
||||
app_parameters, license_test_data[i].usage_entry),
|
||||
Gt(GetLicenseDataSize(license_test_data[i]))))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
}
|
||||
EXPECT_CALL(file, Close()).Times(kNumberOfLicenses);
|
||||
EXPECT_CALL(file, Read(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2355,7 +2367,6 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
|
||||
|
||||
TEST_F(DeviceFilesTest, RetrieveLicenses) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
for (size_t i = 0; i < kNumberOfLicenses; ++i) {
|
||||
std::string license_path = device_base_path_ +
|
||||
@@ -2364,20 +2375,22 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
|
||||
|
||||
size_t size = license_test_data[i].file_data.size();
|
||||
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
|
||||
EXPECT_CALL(file_system, Exists(StrEq(license_path)))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
|
||||
.WillOnce(Return(size));
|
||||
EXPECT_CALL(file_system, Open(StrEq(license_path), _))
|
||||
.WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(size)))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(license_path), _))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(size)))
|
||||
.WillOnce(
|
||||
DoAll(SetArrayArgument<0>(license_test_data[i].file_data.begin(),
|
||||
license_test_data[i].file_data.end()),
|
||||
Return(size)));
|
||||
EXPECT_CALL(*file, Write(_, _)).Times(0);
|
||||
}
|
||||
EXPECT_CALL(file, Close()).Times(kNumberOfLicenses);
|
||||
EXPECT_CALL(file, Write(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2434,19 +2447,19 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
|
||||
|
||||
size_t size = test_data->file_data.size();
|
||||
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, Exists(StrEq(license_path))).WillOnce(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
|
||||
.WillOnce(Return(size));
|
||||
EXPECT_CALL(file_system, Open(StrEq(license_path), _))
|
||||
.WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(size)))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(license_path), _))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(size)))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(test_data->file_data.begin(),
|
||||
test_data->file_data.end()),
|
||||
Return(size)));
|
||||
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(file, Write(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Write(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2489,52 +2502,35 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) {
|
||||
license_update_test_data[0].key_set_id +
|
||||
DeviceFiles::GetLicenseFileNameExtension();
|
||||
|
||||
MockFile file;
|
||||
EXPECT_CALL(file_system, Open(StrEq(license_path), IsCreateFileFlagSet()))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(&file));
|
||||
EXPECT_CALL(file, Write(IsStrEq(license_update_test_data[0].file_data),
|
||||
Eq(license_update_test_data[0].file_data.size())))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Write(IsStrEq(license_update_test_data[1].file_data),
|
||||
Eq(license_update_test_data[1].file_data.size())))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Close()).Times(2);
|
||||
EXPECT_CALL(file, Read(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
EXPECT_TRUE(device_files.StoreLicense(
|
||||
license_update_test_data[0].key_set_id,
|
||||
license_update_test_data[0].license_state,
|
||||
license_update_test_data[0].pssh_data,
|
||||
license_update_test_data[0].key_request,
|
||||
license_update_test_data[0].key_response,
|
||||
license_update_test_data[0].key_renewal_request,
|
||||
license_update_test_data[0].key_renewal_response,
|
||||
license_update_test_data[0].key_release_url,
|
||||
license_update_test_data[0].playback_start_time,
|
||||
license_update_test_data[0].last_playback_time,
|
||||
license_update_test_data[0].grace_period_end_time,
|
||||
GetAppParameters(license_test_data[0].app_parameters),
|
||||
license_update_test_data[0].usage_entry,
|
||||
license_update_test_data[0].usage_entry_number));
|
||||
|
||||
EXPECT_TRUE(device_files.StoreLicense(
|
||||
license_update_test_data[0].key_set_id,
|
||||
license_update_test_data[1].license_state,
|
||||
license_update_test_data[0].pssh_data,
|
||||
license_update_test_data[0].key_request,
|
||||
license_update_test_data[0].key_response,
|
||||
license_update_test_data[0].key_renewal_request,
|
||||
license_update_test_data[0].key_renewal_response,
|
||||
license_update_test_data[0].key_release_url,
|
||||
license_update_test_data[0].playback_start_time,
|
||||
license_update_test_data[0].last_playback_time,
|
||||
license_update_test_data[0].grace_period_end_time,
|
||||
GetAppParameters(license_test_data[0].app_parameters),
|
||||
license_update_test_data[0].usage_entry,
|
||||
license_update_test_data[0].usage_entry_number));
|
||||
for (size_t i = 0; i < sizeof(license_update_test_data) / sizeof(LicenseInfo);
|
||||
i++) {
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(license_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Write(IsStrEq(license_update_test_data[i].file_data),
|
||||
Eq(license_update_test_data[i].file_data.size())))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
EXPECT_TRUE(device_files.StoreLicense(
|
||||
license_update_test_data[0].key_set_id,
|
||||
license_update_test_data[i].license_state,
|
||||
license_update_test_data[0].pssh_data,
|
||||
license_update_test_data[0].key_request,
|
||||
license_update_test_data[0].key_response,
|
||||
license_update_test_data[0].key_renewal_request,
|
||||
license_update_test_data[0].key_renewal_response,
|
||||
license_update_test_data[0].key_release_url,
|
||||
license_update_test_data[0].playback_start_time,
|
||||
license_update_test_data[0].last_playback_time,
|
||||
license_update_test_data[0].grace_period_end_time,
|
||||
GetAppParameters(license_test_data[0].app_parameters),
|
||||
license_update_test_data[0].usage_entry,
|
||||
license_update_test_data[0].usage_entry_number));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DeviceFilesTest, DeleteLicense) {
|
||||
@@ -2545,23 +2541,23 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
|
||||
|
||||
size_t size = license_test_data[0].file_data.size();
|
||||
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, Exists(StrEq(license_path)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true))
|
||||
.WillOnce(Return(false));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
|
||||
.WillOnce(Return(size));
|
||||
EXPECT_CALL(file_system, Open(StrEq(license_path), _))
|
||||
.WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(size)))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(license_path), _))
|
||||
.WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(size)))
|
||||
.WillOnce(
|
||||
DoAll(SetArrayArgument<0>(license_test_data[0].file_data.begin(),
|
||||
license_test_data[0].file_data.end()),
|
||||
Return(size)));
|
||||
EXPECT_CALL(file_system, Remove(StrEq(license_path))).WillOnce(Return(true));
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(file, Write(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Write(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2609,7 +2605,7 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
|
||||
TEST_F(DeviceFilesTest, ReserveLicenseIdsDoesNotUseFileSystem) {
|
||||
// Validate that ReserveLicenseIds does not touch the file system.
|
||||
MockFileSystem file_system;
|
||||
EXPECT_CALL(file_system, Open(_, _)).Times(0);
|
||||
EXPECT_CALL(file_system, DoOpen(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2624,7 +2620,6 @@ TEST_F(DeviceFilesTest, ReserveLicenseIdsDoesNotUseFileSystem) {
|
||||
|
||||
TEST_F(DeviceFilesUsageInfoTest, ListNullParam) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2633,7 +2628,6 @@ TEST_F(DeviceFilesUsageInfoTest, ListNullParam) {
|
||||
|
||||
TEST_F(DeviceFilesUsageInfoTest, ListIdsNull) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
std::string app_id = kUsageInfoTestData[0].app_id;
|
||||
|
||||
@@ -2644,7 +2638,6 @@ TEST_F(DeviceFilesUsageInfoTest, ListIdsNull) {
|
||||
|
||||
TEST_F(DeviceFilesUsageInfoTest, ListUsageIds) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
int index = 8;
|
||||
std::string app_id = kUsageInfoTestData[index].app_id;
|
||||
@@ -2654,22 +2647,21 @@ TEST_F(DeviceFilesUsageInfoTest, ListUsageIds) {
|
||||
std::string file_data = (index < 0) ? kEmptyUsageInfoFileData
|
||||
: kUsageInfoTestData[index].file_data;
|
||||
if (index >= 0) {
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(kUsageInfoTestData[index].file_data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file,
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file,
|
||||
Read(NotNull(), Eq(kUsageInfoTestData[index].file_data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
|
||||
Return(file_data.size())));
|
||||
EXPECT_CALL(file, Close());
|
||||
}
|
||||
else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.WillOnce(Return(false));
|
||||
} else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(false));
|
||||
}
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
@@ -2700,7 +2692,6 @@ TEST_F(DeviceFilesUsageInfoTest, ListUsageIds) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoListTest, UsageInfoList) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
int index = GetParam();
|
||||
std::vector<std::string> file_list;
|
||||
@@ -2729,7 +2720,8 @@ INSTANTIATE_TEST_CASE_P(UsageInfo, DeviceFilesUsageInfoListTest,
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, Store) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
|
||||
int index = GetParam();
|
||||
|
||||
@@ -2761,11 +2753,10 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Write(ContainsAllElementsInVector(usage_data_fields),
|
||||
Gt(usage_data_fields_length)))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Write(ContainsAllElementsInVector(usage_data_fields),
|
||||
Gt(usage_data_fields_length)))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Close());
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -2775,7 +2766,6 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, Retrieve) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
int index = GetParam();
|
||||
|
||||
@@ -2787,22 +2777,21 @@ TEST_P(DeviceFilesUsageInfoTest, Retrieve) {
|
||||
std::string file_data = (index < 0) ? kEmptyUsageInfoFileData
|
||||
: kUsageInfoTestData[index].file_data;
|
||||
if (index >= 0) {
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(kUsageInfoTestData[index].file_data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file,
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file,
|
||||
Read(NotNull(), Eq(kUsageInfoTestData[index].file_data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
|
||||
Return(file_data.size())));
|
||||
EXPECT_CALL(file, Close());
|
||||
}
|
||||
else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.WillOnce(Return(false));
|
||||
} else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(false));
|
||||
}
|
||||
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data_list;
|
||||
@@ -2838,7 +2827,6 @@ TEST_P(DeviceFilesUsageInfoTest, Retrieve) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, ListKeySetIds) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
int index = GetParam();
|
||||
|
||||
@@ -2850,22 +2838,21 @@ TEST_P(DeviceFilesUsageInfoTest, ListKeySetIds) {
|
||||
std::string file_data = (index < 0) ? kEmptyUsageInfoFileData
|
||||
: kUsageInfoTestData[index].file_data;
|
||||
if (index >= 0) {
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(kUsageInfoTestData[index].file_data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file,
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file,
|
||||
Read(NotNull(), Eq(kUsageInfoTestData[index].file_data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
|
||||
Return(file_data.size())));
|
||||
EXPECT_CALL(file, Close());
|
||||
}
|
||||
else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.WillOnce(Return(false));
|
||||
} else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(false));
|
||||
}
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
@@ -2891,7 +2878,6 @@ TEST_P(DeviceFilesUsageInfoTest, ListKeySetIds) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, ListProviderSessionTokenIds) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
|
||||
int index = GetParam();
|
||||
|
||||
@@ -2903,22 +2889,21 @@ TEST_P(DeviceFilesUsageInfoTest, ListProviderSessionTokenIds) {
|
||||
std::string file_data = (index < 0) ? kEmptyUsageInfoFileData
|
||||
: kUsageInfoTestData[index].file_data;
|
||||
if (index >= 0) {
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(kUsageInfoTestData[index].file_data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file,
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file,
|
||||
Read(NotNull(), Eq(kUsageInfoTestData[index].file_data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
|
||||
Return(file_data.size())));
|
||||
EXPECT_CALL(file, Close());
|
||||
}
|
||||
else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path)))
|
||||
.WillOnce(Return(false));
|
||||
} else {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(false));
|
||||
}
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
@@ -2945,7 +2930,8 @@ TEST_P(DeviceFilesUsageInfoTest, ListProviderSessionTokenIds) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
|
||||
int index = GetParam();
|
||||
|
||||
@@ -2968,11 +2954,10 @@ TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.WillOnce(Return(file_data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(file_data.size())))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(file_data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
|
||||
Return(file_data.size())));
|
||||
EXPECT_CALL(file, Close());
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -3002,7 +2987,8 @@ TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) {
|
||||
|
||||
TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
|
||||
int index = GetParam();
|
||||
|
||||
@@ -3066,21 +3052,31 @@ TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) {
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.WillOnce(Return(file_data.size()));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(file_data.size())))
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(file_data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
|
||||
Return(file_data.size())));
|
||||
|
||||
bool write_called = false;
|
||||
if (index < 0) {
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Close());
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
} else {
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _))
|
||||
MockFile* next_file = new MockFile();
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(&file));
|
||||
EXPECT_CALL(file, Write(ContainsAllElementsInVector(usage_data_fields),
|
||||
Gt(usage_data_fields_length)))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Close()).Times(2);
|
||||
.WillOnce(Return(file))
|
||||
.WillOnce(Return(next_file));
|
||||
ON_CALL(*file, Write(ContainsAllElementsInVector(usage_data_fields),
|
||||
Gt(usage_data_fields_length)))
|
||||
.WillByDefault(DoAll(InvokeWithoutArgs([&write_called]() -> void {
|
||||
write_called = true;
|
||||
}),
|
||||
ReturnArg<1>()));
|
||||
ON_CALL(*next_file, Write(ContainsAllElementsInVector(usage_data_fields),
|
||||
Gt(usage_data_fields_length)))
|
||||
.WillByDefault(DoAll(InvokeWithoutArgs([&write_called]() -> void {
|
||||
write_called = true;
|
||||
}),
|
||||
ReturnArg<1>()));
|
||||
}
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
@@ -3090,6 +3086,7 @@ TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) {
|
||||
EXPECT_EQ(expected_result,
|
||||
device_files.UpdateUsageInfo(file_name, provider_session_token,
|
||||
kUsageInfoUpdateTestData));
|
||||
if (index >= 0) EXPECT_TRUE(write_called);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(UsageInfo, DeviceFilesUsageInfoTest,
|
||||
@@ -3097,7 +3094,8 @@ INSTANTIATE_TEST_CASE_P(UsageInfo, DeviceFilesUsageInfoTest,
|
||||
|
||||
TEST_P(DeviceFilesHlsAttributesTest, Read) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
HlsAttributesInfo* param = GetParam();
|
||||
std::string path = device_base_path_ + param->key_set_id +
|
||||
DeviceFiles::GetHlsAttributesFileNameExtension();
|
||||
@@ -3105,14 +3103,13 @@ TEST_P(DeviceFilesHlsAttributesTest, Read) {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.WillRepeatedly(Return(param->file_data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(param->file_data.size())))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(param->file_data.size())))
|
||||
.WillOnce(DoAll(
|
||||
SetArrayArgument<0>(param->file_data.begin(), param->file_data.end()),
|
||||
Return(param->file_data.size())));
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
|
||||
EXPECT_CALL(file, Write(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Write(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -3127,18 +3124,18 @@ TEST_P(DeviceFilesHlsAttributesTest, Read) {
|
||||
|
||||
TEST_P(DeviceFilesHlsAttributesTest, Store) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
HlsAttributesInfo* param = GetParam();
|
||||
std::string path = device_base_path_ + param->key_set_id +
|
||||
DeviceFiles::GetHlsAttributesFileNameExtension();
|
||||
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Write(Contains(param->media_segment_iv, 0),
|
||||
Gt(param->media_segment_iv.size())))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Write(Contains(param->media_segment_iv, 0),
|
||||
Gt(param->media_segment_iv.size())))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Read(_, _)).Times(0);
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -3150,7 +3147,6 @@ TEST_P(DeviceFilesHlsAttributesTest, Store) {
|
||||
|
||||
TEST_P(DeviceFilesHlsAttributesTest, Delete) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
HlsAttributesInfo* param = GetParam();
|
||||
std::string path = device_base_path_ + param->key_set_id +
|
||||
DeviceFiles::GetHlsAttributesFileNameExtension();
|
||||
@@ -3168,7 +3164,8 @@ INSTANTIATE_TEST_CASE_P(HlsAttributes, DeviceFilesHlsAttributesTest,
|
||||
|
||||
TEST_P(DeviceFilesUsageTableTest, Store) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
int index = GetParam();
|
||||
|
||||
size_t entry_data_length = 0;
|
||||
@@ -3188,12 +3185,11 @@ TEST_P(DeviceFilesUsageTableTest, Store) {
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName();
|
||||
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Write(ContainsAllElementsInVector(entry_data),
|
||||
Gt(entry_data_length)))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Write(ContainsAllElementsInVector(entry_data),
|
||||
Gt(entry_data_length)))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(file, Read(_, _)).Times(0);
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -3203,7 +3199,8 @@ TEST_P(DeviceFilesUsageTableTest, Store) {
|
||||
|
||||
TEST_P(DeviceFilesUsageTableTest, Read) {
|
||||
MockFileSystem file_system;
|
||||
MockFile file;
|
||||
// Call to Open will return a unique_ptr, freeing this object.
|
||||
MockFile* file = new MockFile();
|
||||
size_t index = GetParam();
|
||||
|
||||
std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName();
|
||||
@@ -3212,13 +3209,12 @@ TEST_P(DeviceFilesUsageTableTest, Read) {
|
||||
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(file_system, FileSize(StrEq(path)))
|
||||
.WillRepeatedly(Return(file_data.size()));
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
|
||||
EXPECT_CALL(file, Read(NotNull(), Eq(file_data.size())))
|
||||
EXPECT_CALL(file_system, DoOpen(StrEq(path), _)).WillOnce(Return(file));
|
||||
EXPECT_CALL(*file, Read(NotNull(), Eq(file_data.size())))
|
||||
.WillOnce(DoAll(SetArrayArgument<0>(file_data.begin(), file_data.end()),
|
||||
Return(file_data.size())));
|
||||
EXPECT_CALL(file, Close()).Times(1);
|
||||
|
||||
EXPECT_CALL(file, Write(_, _)).Times(0);
|
||||
EXPECT_CALL(*file, Write(_, _)).Times(0);
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
|
||||
@@ -57,9 +57,8 @@ TEST_F(FileTest, OpenFile) {
|
||||
std::string path = test_vectors::kTestDir + kTestFileName;
|
||||
EXPECT_TRUE(file_system.Remove(path));
|
||||
|
||||
File* file = file_system.Open(path, FileSystem::kCreate);
|
||||
std::unique_ptr<File> file = file_system.Open(path, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
}
|
||||
@@ -67,9 +66,8 @@ TEST_F(FileTest, OpenFile) {
|
||||
TEST_F(FileTest, RemoveDirAndFile) {
|
||||
std::string path = test_vectors::kTestDir + kTestFileName;
|
||||
|
||||
File* file = file_system.Open(path, FileSystem::kCreate);
|
||||
std::unique_ptr<File> file = file_system.Open(path, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
EXPECT_TRUE(file_system.Remove(path));
|
||||
@@ -77,7 +75,6 @@ TEST_F(FileTest, RemoveDirAndFile) {
|
||||
|
||||
file = file_system.Open(path, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
RemoveTestDir();
|
||||
@@ -91,12 +88,10 @@ TEST_F(FileTest, RemoveWildcardFiles) {
|
||||
std::string wildcard_path =
|
||||
test_vectors::kTestDir + kWildcard + kTestFileNameExt;
|
||||
|
||||
File* file = file_system.Open(path1, FileSystem::kCreate);
|
||||
std::unique_ptr<File> file = file_system.Open(path1, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
file = file_system.Open(path2, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(file_system.Exists(path1));
|
||||
EXPECT_TRUE(file_system.Exists(path2));
|
||||
@@ -110,13 +105,13 @@ TEST_F(FileTest, FileSize) {
|
||||
file_system.Remove(path);
|
||||
|
||||
std::string write_data = GenerateRandomData(600);
|
||||
File* file = file_system.Open(path, FileSystem::kCreate);
|
||||
size_t write_data_size = write_data.size();
|
||||
std::unique_ptr<File> file = file_system.Open(path, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
|
||||
file->Close();
|
||||
EXPECT_EQ(file->Write(write_data.data(), write_data_size), write_data_size);
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
|
||||
EXPECT_EQ(static_cast<ssize_t>(write_data.size()),
|
||||
EXPECT_EQ(static_cast<ssize_t>(write_data_size),
|
||||
file_system.FileSize(path));
|
||||
}
|
||||
|
||||
@@ -125,18 +120,18 @@ TEST_F(FileTest, WriteReadBinaryFile) {
|
||||
file_system.Remove(path);
|
||||
|
||||
std::string write_data = GenerateRandomData(600);
|
||||
File* file = file_system.Open(path, FileSystem::kCreate);
|
||||
size_t write_data_size = write_data.size();
|
||||
std::unique_ptr<File> file = file_system.Open(path, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
|
||||
file->Close();
|
||||
EXPECT_EQ(file->Write(write_data.data(),write_data_size), write_data_size);
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
|
||||
std::string read_data;
|
||||
read_data.resize(file_system.FileSize(path));
|
||||
size_t read_data_size = read_data.size();
|
||||
file = file_system.Open(path, FileSystem::kReadOnly);
|
||||
ASSERT_TRUE(file);
|
||||
EXPECT_TRUE(file->Read(&read_data[0], read_data.size()));
|
||||
file->Close();
|
||||
EXPECT_EQ(file->Read(&read_data[0], read_data_size), read_data_size);
|
||||
EXPECT_EQ(write_data, read_data);
|
||||
}
|
||||
|
||||
@@ -149,15 +144,12 @@ TEST_F(FileTest, ListFiles) {
|
||||
std::string path3 = test_vectors::kTestDir + kTestFileName3;
|
||||
std::string path_dir = test_vectors::kTestDir;
|
||||
|
||||
File* file = file_system.Open(path1, FileSystem::kCreate);
|
||||
std::unique_ptr<File> file = file_system.Open(path1, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
file = file_system.Open(path2, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
file = file_system.Open(path3, FileSystem::kCreate);
|
||||
ASSERT_TRUE(file);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(file_system.Exists(path1));
|
||||
EXPECT_TRUE(file_system.Exists(path2));
|
||||
@@ -167,7 +159,7 @@ TEST_F(FileTest, ListFiles) {
|
||||
EXPECT_FALSE(file_system.List(not_path, &names));
|
||||
|
||||
// Valid path, but no way to return names.
|
||||
EXPECT_FALSE(file_system.List(path_dir, NULL));
|
||||
EXPECT_FALSE(file_system.List(path_dir, nullptr));
|
||||
|
||||
// Valid path, valid return.
|
||||
EXPECT_TRUE(file_system.List(path_dir, &names));
|
||||
|
||||
@@ -389,9 +389,9 @@ CdmEngine* WvContentDecryptionModule::EnsureCdmForIdentifier(
|
||||
// origin provided by the app and an identifier that uniquely identifies
|
||||
// this CDM. We concatenate all pieces of the CdmIdentifier in order to
|
||||
// create an ID that is unique to that identifier.
|
||||
cdms_[identifier].file_system.SetOrigin(identifier.origin);
|
||||
cdms_[identifier].file_system.SetIdentifier(identifier.spoid +
|
||||
identifier.origin);
|
||||
cdms_[identifier].file_system.set_origin(identifier.origin);
|
||||
cdms_[identifier].file_system.set_identifier(identifier.spoid +
|
||||
identifier.origin);
|
||||
|
||||
// Set the app package name for use by metrics.
|
||||
cdms_[identifier].cdm_engine->GetMetrics()->SetAppPackageName(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "file_store.h"
|
||||
@@ -64,9 +65,8 @@ TEST_F(FileUtilsTest, CreateDirectory) {
|
||||
|
||||
TEST_F(FileUtilsTest, IsDir) {
|
||||
std::string path = test_vectors::kTestDir + kTestFileName;
|
||||
File* file = file_system.Open(path, FileSystem::kCreate);
|
||||
std::unique_ptr<File> file = file_system.Open(path, FileSystem::kCreate);
|
||||
EXPECT_TRUE(file);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
EXPECT_TRUE(file_system.Exists(test_vectors::kTestDir));
|
||||
@@ -76,9 +76,8 @@ TEST_F(FileUtilsTest, IsDir) {
|
||||
|
||||
TEST_F(FileUtilsTest, IsRegularFile) {
|
||||
std::string path = test_vectors::kTestDir + kTestFileName;
|
||||
File* file = file_system.Open(path, FileSystem::kCreate);
|
||||
std::unique_ptr<File> file = file_system.Open(path, FileSystem::kCreate);
|
||||
EXPECT_TRUE(file);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
EXPECT_TRUE(file_system.Exists(test_vectors::kTestDir));
|
||||
@@ -91,10 +90,11 @@ TEST_F(FileUtilsTest, CopyFile) {
|
||||
file_system.Remove(path);
|
||||
|
||||
std::string write_data = GenerateRandomData(600);
|
||||
File* wr_file = file_system.Open(path, FileSystem::kCreate);
|
||||
size_t write_data_size = write_data.size();
|
||||
std::unique_ptr<File> wr_file = file_system.Open(path, FileSystem::kCreate);
|
||||
EXPECT_TRUE(wr_file);
|
||||
EXPECT_TRUE(wr_file->Write(write_data.data(), write_data.size()));
|
||||
wr_file->Close();
|
||||
EXPECT_EQ(wr_file->Write(write_data.data(), write_data_size),
|
||||
write_data_size);
|
||||
ASSERT_TRUE(file_system.Exists(path));
|
||||
|
||||
std::string path_copy = test_vectors::kTestDir + kTestFileName2;
|
||||
@@ -103,10 +103,11 @@ TEST_F(FileUtilsTest, CopyFile) {
|
||||
|
||||
std::string read_data;
|
||||
read_data.resize(file_system.FileSize(path_copy));
|
||||
File* rd_file = file_system.Open(path_copy, FileSystem::kReadOnly);
|
||||
size_t read_data_size = read_data.size();
|
||||
std::unique_ptr<File> rd_file =
|
||||
file_system.Open(path_copy, FileSystem::kReadOnly);
|
||||
EXPECT_TRUE(rd_file);
|
||||
EXPECT_TRUE(rd_file->Read(&read_data[0], read_data.size()));
|
||||
rd_file->Close();
|
||||
EXPECT_EQ(rd_file->Read(&read_data[0], read_data_size), read_data_size);
|
||||
EXPECT_EQ(write_data, read_data);
|
||||
EXPECT_EQ(file_system.FileSize(path), file_system.FileSize(path_copy));
|
||||
}
|
||||
@@ -123,18 +124,18 @@ TEST_F(FileUtilsTest, ListFiles) {
|
||||
|
||||
path = test_vectors::kTestDir + kTestFileName;
|
||||
std::string write_data = GenerateRandomData(600);
|
||||
File* file = file_system.Open(path, FileSystem::kCreate);
|
||||
size_t write_data_size = write_data.size();
|
||||
std::unique_ptr<File> file = file_system.Open(path, FileSystem::kCreate);
|
||||
EXPECT_TRUE(file);
|
||||
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
|
||||
file->Close();
|
||||
EXPECT_EQ(file->Write(write_data.data(), write_data_size), write_data_size);
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
|
||||
path = test_vectors::kTestDir + kTestFileName2;
|
||||
write_data = GenerateRandomData(600);
|
||||
write_data_size = write_data.size();
|
||||
file = file_system.Open(path, FileSystem::kCreate);
|
||||
EXPECT_TRUE(file);
|
||||
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
|
||||
file->Close();
|
||||
EXPECT_EQ(file->Write(write_data.data(), write_data_size), write_data_size);
|
||||
EXPECT_TRUE(file_system.Exists(path));
|
||||
|
||||
std::vector<std::string> files;
|
||||
|
||||
@@ -3357,7 +3357,7 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
|
||||
ssize_t file_size =
|
||||
file_system.FileSize(usage_info_not_empty_app_id_file_name);
|
||||
EXPECT_LT(4, file_size);
|
||||
File* file =
|
||||
std::unique_ptr<File> file =
|
||||
file_system.Open(usage_info_not_empty_app_id_file_name,
|
||||
FileSystem::kReadOnly);
|
||||
EXPECT_TRUE(NULL != file);
|
||||
@@ -3365,7 +3365,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
|
||||
file_data.resize(file_size);
|
||||
ssize_t bytes = file->Read(&file_data[0], file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
// Corrupt the hash of the usage info file with non-empty app id and write
|
||||
// it back out
|
||||
@@ -3375,7 +3374,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
|
||||
EXPECT_TRUE(NULL != file);
|
||||
bytes = file->Write(file_data.data(), file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
@@ -3404,7 +3402,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
|
||||
file_data.resize(file_size);
|
||||
bytes = file->Read(&file_data[0], file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
// Corrupt the hash of the usage info file with empty app id and write it
|
||||
// back out
|
||||
@@ -3414,7 +3411,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
|
||||
EXPECT_TRUE(NULL != file);
|
||||
bytes = file->Write(file_data.data(), file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
@@ -3507,7 +3503,7 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest2) {
|
||||
ssize_t file_size =
|
||||
file_system.FileSize(usage_info_not_empty_app_id_file_name);
|
||||
EXPECT_LT(4, file_size);
|
||||
File* file =
|
||||
std::unique_ptr<File> file =
|
||||
file_system.Open(usage_info_not_empty_app_id_file_name,
|
||||
FileSystem::kReadOnly);
|
||||
EXPECT_TRUE(NULL != file);
|
||||
@@ -3515,7 +3511,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest2) {
|
||||
file_data.resize(file_size);
|
||||
ssize_t bytes = file->Read(&file_data[0], file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
video_widevine_client::sdk::HashedFile hash_file;
|
||||
|
||||
@@ -3533,7 +3528,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest2) {
|
||||
EXPECT_TRUE(NULL != file);
|
||||
bytes = file->Write(file_data.data(), file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
@@ -3562,7 +3556,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest2) {
|
||||
file_data.resize(file_size);
|
||||
bytes = file->Read(&file_data[0], file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
EXPECT_TRUE(hash_file.ParseFromString(file_data));
|
||||
pos = file_data.find(hash_file.hash());
|
||||
@@ -3578,7 +3571,6 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest2) {
|
||||
EXPECT_TRUE(NULL != file);
|
||||
bytes = file->Write(file_data.data(), file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
@@ -3805,14 +3797,13 @@ TEST_F(WvCdmRequestLicenseTest, UsageRecoveryTest) {
|
||||
// Read in usage info file
|
||||
ssize_t file_size = file_system.FileSize(usage_info_file_name);
|
||||
EXPECT_LT(4, file_size);
|
||||
File* file =
|
||||
std::unique_ptr<File> file =
|
||||
file_system.Open(usage_info_file_name, FileSystem::kReadOnly);
|
||||
EXPECT_TRUE(NULL != file);
|
||||
std::string file_data;
|
||||
file_data.resize(file_size);
|
||||
ssize_t bytes = file->Read(&file_data[0], file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
// Corrupt the hash of the usage info file and write it back out
|
||||
memset(&file_data[0]+bytes-4, 0, 4);
|
||||
@@ -3821,7 +3812,6 @@ TEST_F(WvCdmRequestLicenseTest, UsageRecoveryTest) {
|
||||
EXPECT_TRUE(NULL != file);
|
||||
bytes = file->Write(file_data.data(), file_data.size());
|
||||
EXPECT_EQ(file_size, bytes);
|
||||
file->Close();
|
||||
|
||||
// Fetch a second usage license, this should fail as the usage table is
|
||||
// corrupt
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define WVCDM_UTIL_FILE_STORE_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -18,18 +19,10 @@ namespace wvcdm {
|
||||
// File class. The implementation is platform dependent.
|
||||
class File {
|
||||
public:
|
||||
virtual ssize_t Read(char* buffer, size_t bytes);
|
||||
virtual ssize_t Write(const char* buffer, size_t bytes);
|
||||
virtual void Close();
|
||||
|
||||
protected:
|
||||
class Impl;
|
||||
|
||||
File(Impl*);
|
||||
virtual ~File();
|
||||
|
||||
private:
|
||||
Impl* impl_;
|
||||
File() {}
|
||||
virtual ~File() {}
|
||||
virtual ssize_t Read(char* buffer, size_t bytes) = 0;
|
||||
virtual ssize_t Write(const char* buffer, size_t bytes) = 0;
|
||||
|
||||
friend class FileSystem;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(File);
|
||||
@@ -37,6 +30,10 @@ class File {
|
||||
|
||||
class FileSystem {
|
||||
public:
|
||||
FileSystem();
|
||||
FileSystem(const std::string& origin, void* extra_data);
|
||||
virtual ~FileSystem();
|
||||
|
||||
class Impl;
|
||||
|
||||
// defines as bit flag
|
||||
@@ -47,11 +44,7 @@ class FileSystem {
|
||||
kTruncate = 4
|
||||
};
|
||||
|
||||
FileSystem();
|
||||
FileSystem(const std::string& origin, void* extra_data);
|
||||
virtual ~FileSystem();
|
||||
|
||||
virtual File* Open(const std::string& file_path, int flags);
|
||||
virtual std::unique_ptr<File> Open(const std::string& file_path, int flags);
|
||||
|
||||
virtual bool Exists(const std::string& file_path);
|
||||
virtual bool Remove(const std::string& file_path);
|
||||
@@ -63,14 +56,14 @@ class FileSystem {
|
||||
std::vector<std::string>* names);
|
||||
|
||||
const std::string& origin() const { return origin_; }
|
||||
void SetOrigin(const std::string& origin);
|
||||
void set_origin(const std::string& origin);
|
||||
|
||||
const std::string& identifier() const { return identifier_; }
|
||||
void SetIdentifier(const std::string& identifier);
|
||||
void set_identifier(const std::string& identifier);
|
||||
bool IsGlobal() const { return identifier_.empty(); }
|
||||
|
||||
private:
|
||||
Impl* impl_;
|
||||
std::unique_ptr<FileSystem::Impl> impl_;
|
||||
std::string origin_;
|
||||
std::string identifier_;
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "file_utils.h"
|
||||
#include "log.h"
|
||||
@@ -60,65 +62,70 @@ std::string GetFileNameForIdentifier(const std::string path,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class File::Impl {
|
||||
class FileImpl : public File {
|
||||
public:
|
||||
Impl(FILE* file, const std::string& file_path)
|
||||
FileImpl(FILE* file, const std::string& file_path)
|
||||
: file_(file), file_path_(file_path) {}
|
||||
virtual ~Impl() {}
|
||||
|
||||
void FlushFile() {
|
||||
fflush(file_);
|
||||
fsync(fileno(file_));
|
||||
}
|
||||
|
||||
~FileImpl() {
|
||||
if (file_) {
|
||||
FlushFile();
|
||||
fclose(file_);
|
||||
file_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t Read(char* buffer, size_t bytes) override {
|
||||
if (!buffer) {
|
||||
LOGW("File::Read: buffer is empty");
|
||||
return -1;
|
||||
}
|
||||
if (!file_) {
|
||||
LOGW("File::Read: file not open");
|
||||
return -1;
|
||||
}
|
||||
size_t len = fread(buffer, sizeof(char), bytes, file_);
|
||||
if (len != bytes) {
|
||||
LOGW("File::Read: fread failed: %d, %s", errno, strerror(errno));
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t Write(const char* buffer, size_t bytes) override {
|
||||
if (!buffer) {
|
||||
LOGW("File::Write: buffer is empty");
|
||||
return -1;
|
||||
}
|
||||
if (!file_) {
|
||||
LOGW("File::Write: file not open");
|
||||
return -1;
|
||||
}
|
||||
size_t len = fwrite(buffer, sizeof(char), bytes, file_);
|
||||
if (len != bytes) {
|
||||
LOGW("File::Write: fwrite failed: %d, %s", errno, strerror(errno));
|
||||
}
|
||||
FlushFile();
|
||||
return len;
|
||||
}
|
||||
|
||||
FILE* file_;
|
||||
std::string file_path_;
|
||||
};
|
||||
|
||||
File::File(Impl* impl) : impl_(impl) {}
|
||||
|
||||
File::~File() {
|
||||
Close();
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void File::Close() {
|
||||
if (impl_ && impl_->file_) {
|
||||
fflush(impl_->file_);
|
||||
fsync(fileno(impl_->file_));
|
||||
fclose(impl_->file_);
|
||||
impl_->file_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t File::Read(char* buffer, size_t bytes) {
|
||||
if (impl_ && impl_->file_) {
|
||||
size_t len = fread(buffer, sizeof(char), bytes, impl_->file_);
|
||||
if (len == 0) {
|
||||
LOGW("File::Read: fread failed: %d", errno);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
LOGW("File::Read: file not open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t File::Write(const char* buffer, size_t bytes) {
|
||||
if (impl_ && impl_->file_) {
|
||||
size_t len = fwrite(buffer, sizeof(char), bytes, impl_->file_);
|
||||
if (len == 0) {
|
||||
LOGW("File::Write: fwrite failed: %d", errno);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
LOGW("File::Write: file not open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
class FileSystem::Impl {};
|
||||
|
||||
FileSystem::FileSystem() : FileSystem(EMPTY_ORIGIN, NULL) {}
|
||||
FileSystem::FileSystem() : FileSystem(EMPTY_ORIGIN, nullptr) {}
|
||||
FileSystem::FileSystem(const std::string& origin, void* /* extra_data */)
|
||||
: origin_(origin) {}
|
||||
|
||||
FileSystem::~FileSystem() {}
|
||||
|
||||
File* FileSystem::Open(const std::string& in_name, int flags) {
|
||||
std::unique_ptr<File> FileSystem::Open(const std::string& in_name, int flags) {
|
||||
std::string open_flags;
|
||||
|
||||
std::string name = GetFileNameForIdentifier(in_name, identifier_);
|
||||
@@ -146,11 +153,11 @@ File* FileSystem::Open(const std::string& in_name, int flags) {
|
||||
FILE* file = fopen(name.c_str(), open_flags.c_str());
|
||||
umask(old_mask);
|
||||
if (!file) {
|
||||
LOGW("File::Open: fopen failed: %d", errno);
|
||||
return NULL;
|
||||
LOGW("File::Open: fopen failed: %d, %s", errno, strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new File(new File::Impl(file, name));
|
||||
return std::unique_ptr<File>(new FileImpl(file, name));
|
||||
}
|
||||
|
||||
bool FileSystem::Exists(const std::string& path) {
|
||||
@@ -175,9 +182,9 @@ bool FileSystem::List(const std::string& path,
|
||||
return FileUtils::List(GetFileNameForIdentifier(path, origin_), filenames);
|
||||
}
|
||||
|
||||
void FileSystem::SetOrigin(const std::string& origin) { origin_ = origin; }
|
||||
void FileSystem::set_origin(const std::string& origin) { origin_ = origin; }
|
||||
|
||||
void FileSystem::SetIdentifier(const std::string& identifier) {
|
||||
void FileSystem::set_identifier(const std::string& identifier) {
|
||||
identifier_ = identifier;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
@@ -28,7 +29,7 @@ bool FileUtils::Exists(const std::string& path) {
|
||||
struct stat buf;
|
||||
int res = stat(path.c_str(), &buf) == 0;
|
||||
if (!res) {
|
||||
LOGV("File::Exists: stat failed: %d", errno);
|
||||
LOGV("File::Exists: stat failed: %d, %s", errno, strerror(errno));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -53,7 +54,7 @@ bool FileUtils::Remove(const std::string& path) {
|
||||
closedir(dir);
|
||||
}
|
||||
if (rmdir(path.c_str())) {
|
||||
LOGW("File::Remove: rmdir failed: %d", errno);
|
||||
LOGW("File::Remove: rmdir failed: %d, %s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -62,7 +63,7 @@ bool FileUtils::Remove(const std::string& path) {
|
||||
if (wildcard_pos == std::string::npos) {
|
||||
// Handle file deletion
|
||||
if (unlink(path.c_str()) && (errno != ENOENT)) {
|
||||
LOGW("File::Remove: unlink failed: %d", errno);
|
||||
LOGW("File::Remove: unlink failed: %d, %s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -106,19 +107,22 @@ bool FileUtils::Remove(const std::string& path) {
|
||||
bool FileUtils::Copy(const std::string& src, const std::string& dest) {
|
||||
struct stat stat_buf;
|
||||
if (stat(src.c_str(), &stat_buf)) {
|
||||
LOGV("File::Copy: file %s stat error: %d", src.c_str(), errno);
|
||||
LOGV("File::Copy: file %s stat error: %d, %s", src.c_str(), errno,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd_src = open(src.c_str(), O_RDONLY);
|
||||
if (fd_src < 0) {
|
||||
LOGW("File::Copy: unable to open file %s: %d", src.c_str(), errno);
|
||||
LOGW("File::Copy: unable to open file %s: %d, %s", src.c_str(), errno,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd_dest = open(dest.c_str(), O_WRONLY | O_CREAT, stat_buf.st_mode);
|
||||
if (fd_dest < 0) {
|
||||
LOGW("File::Copy: unable to open file %s: %d", dest.c_str(), errno);
|
||||
LOGW("File::Copy: unable to open file %s: %d, %s", dest.c_str(), errno,
|
||||
strerror(errno));
|
||||
close(fd_src);
|
||||
return false;
|
||||
}
|
||||
@@ -126,8 +130,8 @@ bool FileUtils::Copy(const std::string& src, const std::string& dest) {
|
||||
off_t offset = 0;
|
||||
bool status = true;
|
||||
if (sendfile(fd_dest, fd_src, &offset, stat_buf.st_size) < 0) {
|
||||
LOGV("File::Copy: unable to copy %s to %s: %d", src.c_str(), dest.c_str(),
|
||||
errno);
|
||||
LOGV("File::Copy: unable to copy %s to %s: %d, %s", src.c_str(),
|
||||
dest.c_str(), errno, strerror(errno));
|
||||
status = false;
|
||||
}
|
||||
|
||||
@@ -143,13 +147,15 @@ bool FileUtils::List(const std::string& path, std::vector<std::string>* files) {
|
||||
}
|
||||
|
||||
if (!FileUtils::Exists(path)) {
|
||||
LOGV("File::List: path %s does not exist: %d", path.c_str(), errno);
|
||||
LOGV("File::List: path %s does not exist: %d, %s", path.c_str(), errno,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
DIR* dir = opendir(path.c_str());
|
||||
if (dir == NULL) {
|
||||
LOGW("File::List: unable to open directory %s: %d", path.c_str(), errno);
|
||||
LOGW("File::List: unable to open directory %s: %d, %s", path.c_str(), errno,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -193,7 +199,8 @@ bool FileUtils::CreateDirectory(const std::string& path_in) {
|
||||
path[pos] = '\0';
|
||||
if (mkdir(path.c_str(), 0700) != 0) {
|
||||
if (errno != EEXIST) {
|
||||
LOGW("File::CreateDirectory: mkdir failed: %d\n", errno);
|
||||
LOGW("File::CreateDirectory: mkdir failed: %d, %s\n", errno,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -204,7 +211,8 @@ bool FileUtils::CreateDirectory(const std::string& path_in) {
|
||||
if (path[size - 1] != kDirectoryDelimiter) {
|
||||
if (mkdir(path.c_str(), 0700) != 0) {
|
||||
if (errno != EEXIST) {
|
||||
LOGW("File::CreateDirectory: mkdir failed: %d\n", errno);
|
||||
LOGW("File::CreateDirectory: mkdir failed: %d, %s\n", errno,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include "level3_file_system.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "file_store.h"
|
||||
|
||||
namespace wvoec3 {
|
||||
@@ -29,7 +31,7 @@ class OEMCrypto_Level3AndroidFileSystem : public OEMCrypto_Level3FileSystem {
|
||||
|
||||
private:
|
||||
std::string base_path_;
|
||||
wvcdm::FileSystem *file_system_;
|
||||
std::unique_ptr<wvcdm::FileSystem> file_system_;
|
||||
};
|
||||
|
||||
} // namespace wvoec3
|
||||
|
||||
@@ -16,7 +16,7 @@ using wvcdm::FileSystem;
|
||||
namespace wvoec3 {
|
||||
|
||||
OEMCrypto_Level3AndroidFileSystem::OEMCrypto_Level3AndroidFileSystem()
|
||||
: file_system_(new FileSystem) {
|
||||
: file_system_(new FileSystem()) {
|
||||
const char kDirectoryDelimiter = '/';
|
||||
wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
|
||||
&base_path_);
|
||||
@@ -42,19 +42,15 @@ OEMCrypto_Level3AndroidFileSystem::OEMCrypto_Level3AndroidFileSystem()
|
||||
}
|
||||
}
|
||||
|
||||
OEMCrypto_Level3AndroidFileSystem::~OEMCrypto_Level3AndroidFileSystem() {
|
||||
delete file_system_;
|
||||
file_system_ = NULL;
|
||||
}
|
||||
OEMCrypto_Level3AndroidFileSystem::~OEMCrypto_Level3AndroidFileSystem() {}
|
||||
|
||||
ssize_t OEMCrypto_Level3AndroidFileSystem::Read(const char *filename,
|
||||
void *buffer, size_t size) {
|
||||
File *file = file_system_->Open(base_path_ + std::string(filename),
|
||||
FileSystem::kReadOnly);
|
||||
auto file = file_system_->Open(base_path_ + std::string(filename),
|
||||
FileSystem::kReadOnly);
|
||||
ssize_t bytes_read = 0;
|
||||
if (file) {
|
||||
bytes_read = file->Read(static_cast<char *>(buffer), size);
|
||||
file->Close();
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
@@ -62,12 +58,11 @@ ssize_t OEMCrypto_Level3AndroidFileSystem::Read(const char *filename,
|
||||
ssize_t OEMCrypto_Level3AndroidFileSystem::Write(const char *filename,
|
||||
const void *buffer,
|
||||
size_t size) {
|
||||
File *file = file_system_->Open(base_path_ + std::string(filename),
|
||||
FileSystem::kCreate | FileSystem::kTruncate);
|
||||
auto file = file_system_->Open(base_path_ + std::string(filename),
|
||||
FileSystem::kCreate | FileSystem::kTruncate);
|
||||
ssize_t bytes_written = 0;
|
||||
if (file) {
|
||||
bytes_written = file->Write(static_cast<const char *>(buffer), size);
|
||||
file->Close();
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ time_t CryptoEngine::RollbackCorrectedOfflineTime() {
|
||||
// Use the device key for encrypt/decrypt.
|
||||
const std::vector<uint8_t>& key = DeviceRootKey();
|
||||
|
||||
wvcdm::File* file;
|
||||
std::unique_ptr<wvcdm::File> file;
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
@@ -140,7 +140,6 @@ time_t CryptoEngine::RollbackCorrectedOfflineTime() {
|
||||
return time(NULL);
|
||||
}
|
||||
file->Read(reinterpret_cast<char*>(&encrypted_buffer[0]), sizeof(TimeInfo));
|
||||
file->Close();
|
||||
// Decrypt the encrypted TimeInfo buffer.
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(&key[0], 128, &aes_key);
|
||||
@@ -180,7 +179,6 @@ time_t CryptoEngine::RollbackCorrectedOfflineTime() {
|
||||
return time(NULL);
|
||||
}
|
||||
file->Write(reinterpret_cast<char*>(&encrypted_buffer[0]), sizeof(TimeInfo));
|
||||
file->Close();
|
||||
|
||||
// Return time with offset.
|
||||
return current_time;
|
||||
|
||||
@@ -64,7 +64,7 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
|
||||
|
||||
// Load saved table.
|
||||
wvcdm::FileSystem *file_system = ce->file_system();
|
||||
wvcdm::File *file;
|
||||
std::unique_ptr<wvcdm::File> file;
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
@@ -93,7 +93,6 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
|
||||
return;
|
||||
}
|
||||
file->Read(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file->Close();
|
||||
|
||||
// Verify the signature of the usage table file.
|
||||
|
||||
@@ -148,7 +147,6 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
|
||||
return;
|
||||
}
|
||||
file->Read(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
|
||||
file->Close();
|
||||
if ((stored_table->generation > generation_ + 1) ||
|
||||
(stored_table->generation < generation_ - 1)) {
|
||||
LOGE("OldUsageTable: Rollback detected. Clearing Usage Table. %lx -> %lx",
|
||||
|
||||
@@ -669,7 +669,7 @@ bool UsageTable::SaveGenerationNumber() {
|
||||
// On a real implementation, you should NOT put the generation number in
|
||||
// a file in user space. It should be stored in secure memory.
|
||||
std::string filename = path + "GenerationNumber.dat";
|
||||
wvcdm::File* file = file_system->Open(
|
||||
auto file = file_system->Open(
|
||||
filename, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate);
|
||||
if (!file) {
|
||||
LOGE("UsageTable: File open failed: %s", path.c_str());
|
||||
@@ -677,7 +677,6 @@ bool UsageTable::SaveGenerationNumber() {
|
||||
}
|
||||
file->Write(reinterpret_cast<char*>(&master_generation_number_),
|
||||
sizeof(int64_t));
|
||||
file->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -696,7 +695,7 @@ bool UsageTable::LoadGenerationNumber(bool or_make_new_one) {
|
||||
// On a real implementation, you should NOT put the generation number in
|
||||
// a file in user space. It should be stored in secure memory.
|
||||
std::string filename = path + "GenerationNumber.dat";
|
||||
wvcdm::File* file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
|
||||
auto file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
if (or_make_new_one) {
|
||||
RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
|
||||
@@ -709,7 +708,6 @@ bool UsageTable::LoadGenerationNumber(bool or_make_new_one) {
|
||||
}
|
||||
file->Read(reinterpret_cast<char*>(&master_generation_number_),
|
||||
sizeof(int64_t));
|
||||
file->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user