1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/mojo/services/mojo_cdm_helper.h"
7 #include "base/functional/bind.h"
8 #include "base/run_loop.h"
9 #include "base/test/task_environment.h"
10 #include "build/build_config.h"
11 #include "media/cdm/api/content_decryption_module.h"
12 #include "media/mojo/mojom/cdm_storage.mojom.h"
13 #include "mojo/public/cpp/bindings/associated_receiver.h"
14 #include "mojo/public/cpp/bindings/pending_receiver.h"
15 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "url/origin.h"
20 using Status = cdm::FileIOClient::Status;
26 class MockFileIOClient : public cdm::FileIOClient {
28 MockFileIOClient() = default;
29 ~MockFileIOClient() override = default;
31 MOCK_METHOD1(OnOpenComplete, void(Status));
32 MOCK_METHOD3(OnReadComplete, void(Status, const uint8_t*, uint32_t));
33 MOCK_METHOD1(OnWriteComplete, void(Status));
36 class TestCdmFile : public mojom::CdmFile {
38 TestCdmFile() = default;
39 ~TestCdmFile() override = default;
41 // Reading always succeeds with a 3-byte buffer.
42 void Read(ReadCallback callback) override {
43 std::move(callback).Run(Status::kSuccess, {1, 2, 3});
46 // Writing always succeeds.
47 void Write(const std::vector<uint8_t>& data,
48 WriteCallback callback) override {
49 std::move(callback).Run(Status::kSuccess);
53 class MockCdmStorage : public mojom::CdmStorage {
55 MockCdmStorage() = default;
56 ~MockCdmStorage() override = default;
58 void Open(const std::string& file_name, OpenCallback callback) override {
59 std::move(callback).Run(mojom::CdmStorage::Status::kSuccess,
60 client_receiver_.BindNewEndpointAndPassRemote());
64 TestCdmFile cdm_file_;
65 mojo::AssociatedReceiver<mojom::CdmFile> client_receiver_{&cdm_file_};
68 class TestFrameInterfaceFactory : public mojom::FrameInterfaceFactory {
70 void CreateProvisionFetcher(
71 mojo::PendingReceiver<mojom::ProvisionFetcher>) override {}
72 void CreateCdmStorage(
73 mojo::PendingReceiver<mojom::CdmStorage> receiver) override {
74 mojo::MakeSelfOwnedReceiver(std::make_unique<MockCdmStorage>(),
78 void RegisterMuteStateObserver(
79 mojo::PendingRemote<mojom::MuteStateObserver> observer) override {}
80 void CreateDCOMPSurfaceRegistry(
81 mojo::PendingReceiver<mojom::DCOMPSurfaceRegistry> receiver) override {}
82 #endif // BUILDFLAG(IS_WIN)
83 void GetCdmOrigin(GetCdmOriginCallback callback) override {}
84 void BindEmbedderReceiver(mojo::GenericPendingReceiver) override {}
89 class MojoCdmHelperTest : public testing::Test {
91 MojoCdmHelperTest() : helper_(&frame_interfaces_) {}
92 ~MojoCdmHelperTest() override = default;
94 base::test::TaskEnvironment task_environment_;
95 TestFrameInterfaceFactory frame_interfaces_;
96 MockFileIOClient file_io_client_;
97 MojoCdmHelper helper_;
100 TEST_F(MojoCdmHelperTest, CreateCdmFileIO_OpenClose) {
101 cdm::FileIO* file_io = helper_.CreateCdmFileIO(&file_io_client_);
102 const std::string kFileName = "openfile";
103 EXPECT_CALL(file_io_client_, OnOpenComplete(Status::kSuccess));
104 file_io->Open(kFileName.data(), kFileName.length());
105 base::RunLoop().RunUntilIdle();
107 // Close the file as required by cdm::FileIO API.
109 base::RunLoop().RunUntilIdle();
112 // Simulate the case where the CDM didn't call Close(). In this case we still
113 // should not leak the cdm::FileIO object. LeakSanitizer bots should be able to
114 // catch such issues.
115 TEST_F(MojoCdmHelperTest, CreateCdmFileIO_OpenWithoutClose) {
116 cdm::FileIO* file_io = helper_.CreateCdmFileIO(&file_io_client_);
117 const std::string kFileName = "openfile";
118 EXPECT_CALL(file_io_client_, OnOpenComplete(Status::kSuccess));
119 file_io->Open(kFileName.data(), kFileName.length());
120 // file_io->Close() is NOT called.
121 base::RunLoop().RunUntilIdle();
124 // TODO(crbug.com/773860): Add more test cases.