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:
Srujan Gaddam
2018-11-14 16:59:00 -08:00
parent 5d360abd4b
commit 896ce2b5aa
15 changed files with 335 additions and 362 deletions

View File

@@ -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");

View File

@@ -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.

View File

@@ -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));

View File

@@ -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));

View File

@@ -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(

View File

@@ -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;

View File

@@ -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

View File

@@ -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_;

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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",

View File

@@ -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;
}