1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chromeos/components/cdm_factory_daemon/cdm_storage_adapter.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "mojo/public/cpp/bindings/callback_helpers.h"
11 
12 namespace chromeos {
13 
14 namespace {
15 
16 // Helper function to adapt Exists using Read since CdmStorage doesn't have an
17 // Exists implementation. We test it by seeing if the file is non-empty.
ReadToExists(cdm::mojom::CdmStorage::ExistsCallback callback,bool success,const std::vector<uint8_t> & data)18 void ReadToExists(cdm::mojom::CdmStorage::ExistsCallback callback,
19                   bool success,
20                   const std::vector<uint8_t>& data) {
21   std::move(callback).Run(success && !data.empty());
22 }
23 
24 // Helper function to adapt GetSize using Read since CdmFile doesn't have a
25 // GetSize implementation. We get the size by reading the file contents and
26 // determining the length. These files will be small in size and are accessed
27 // infrequently, so this isn't that much of a penalty to pay.
ReadToGetSize(cdm::mojom::CdmStorage::GetSizeCallback callback,bool success,const std::vector<uint8_t> & data)28 void ReadToGetSize(cdm::mojom::CdmStorage::GetSizeCallback callback,
29                    bool success,
30                    const std::vector<uint8_t>& data) {
31   std::move(callback).Run(success, data.size());
32 }
33 
34 }  // namespace
35 
CdmStorageAdapter(media::mojom::FrameInterfaceFactory * frame_interfaces,mojo::PendingAssociatedReceiver<chromeos::cdm::mojom::CdmStorage> receiver)36 CdmStorageAdapter::CdmStorageAdapter(
37     media::mojom::FrameInterfaceFactory* frame_interfaces,
38     mojo::PendingAssociatedReceiver<chromeos::cdm::mojom::CdmStorage> receiver)
39     : receiver_(this, std::move(receiver)) {
40   CHECK(frame_interfaces);
41   frame_interfaces->CreateCdmStorage(
42       cdm_storage_remote_.BindNewPipeAndPassReceiver());
43 }
44 
45 CdmStorageAdapter::~CdmStorageAdapter() = default;
46 
Read(const std::string & file_name,ReadCallback callback)47 void CdmStorageAdapter::Read(const std::string& file_name,
48                              ReadCallback callback) {
49   DVLOG(1) << "Read " << file_name;
50   CHECK(!cdm_file_);
51   auto wrapped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
52       std::move(callback), false, std::vector<uint8_t>());
53   cdm_storage_remote_->Open(
54       file_name,
55       base::BindOnce(&CdmStorageAdapter::OnOpenForRead,
56                      weak_factory_.GetWeakPtr(), std::move(wrapped_callback)));
57 }
58 
OnOpenForRead(ReadCallback callback,media::mojom::CdmStorage::Status status,mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file)59 void CdmStorageAdapter::OnOpenForRead(
60     ReadCallback callback,
61     media::mojom::CdmStorage::Status status,
62     mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file) {
63   if (status != media::mojom::CdmStorage::Status::kSuccess) {
64     std::move(callback).Run(false, {});
65     return;
66   }
67   cdm_file_.Bind(std::move(cdm_file));
68   cdm_file_->Read(base::BindOnce(&CdmStorageAdapter::OnReadComplete,
69                                  weak_factory_.GetWeakPtr(),
70                                  std::move(callback)));
71 }
72 
OnReadComplete(ReadCallback callback,media::mojom::CdmFile::Status status,const std::vector<uint8_t> & data)73 void CdmStorageAdapter::OnReadComplete(ReadCallback callback,
74                                        media::mojom::CdmFile::Status status,
75                                        const std::vector<uint8_t>& data) {
76   cdm_file_.reset();
77   if (status != media::mojom::CdmFile::Status::kSuccess) {
78     std::move(callback).Run(false, {});
79     return;
80   }
81   std::move(callback).Run(true, data);
82 }
83 
Write(const std::string & file_name,const std::vector<uint8_t> & data,WriteCallback callback)84 void CdmStorageAdapter::Write(const std::string& file_name,
85                               const std::vector<uint8_t>& data,
86                               WriteCallback callback) {
87   DVLOG(1) << "Write " << file_name;
88   CHECK(!cdm_file_);
89   auto wrapped_callback =
90       mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback), false);
91   cdm_storage_remote_->Open(file_name,
92                             base::BindOnce(&CdmStorageAdapter::OnOpenForWrite,
93                                            weak_factory_.GetWeakPtr(), data,
94                                            std::move(wrapped_callback)));
95 }
96 
OnOpenForWrite(const std::vector<uint8_t> & data,WriteCallback callback,media::mojom::CdmStorage::Status status,mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file)97 void CdmStorageAdapter::OnOpenForWrite(
98     const std::vector<uint8_t>& data,
99     WriteCallback callback,
100     media::mojom::CdmStorage::Status status,
101     mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file) {
102   if (status != media::mojom::CdmStorage::Status::kSuccess) {
103     std::move(callback).Run(false);
104     return;
105   }
106   cdm_file_.Bind(std::move(cdm_file));
107   cdm_file_->Write(
108       data, base::BindOnce(&CdmStorageAdapter::OnWriteComplete,
109                            weak_factory_.GetWeakPtr(), std::move(callback)));
110 }
111 
OnWriteComplete(WriteCallback callback,media::mojom::CdmFile::Status status)112 void CdmStorageAdapter::OnWriteComplete(WriteCallback callback,
113                                         media::mojom::CdmFile::Status status) {
114   cdm_file_.reset();
115   std::move(callback).Run(status == media::mojom::CdmFile::Status::kSuccess);
116 }
117 
Exists(const std::string & file_name,ExistsCallback callback)118 void CdmStorageAdapter::Exists(const std::string& file_name,
119                                ExistsCallback callback) {
120   DVLOG(1) << "Exists " << file_name;
121   Read(file_name, base::BindOnce(&ReadToExists, std::move(callback)));
122 }
123 
GetSize(const std::string & file_name,GetSizeCallback callback)124 void CdmStorageAdapter::GetSize(const std::string& file_name,
125                                 GetSizeCallback callback) {
126   DVLOG(1) << "GetSize " << file_name;
127   Read(file_name, base::BindOnce(&ReadToGetSize, std::move(callback)));
128 }
129 
Remove(const std::string & file_name,RemoveCallback callback)130 void CdmStorageAdapter::Remove(const std::string& file_name,
131                                RemoveCallback callback) {
132   DVLOG(1) << "Remove " << file_name;
133   // Writing a zero length array to the file removes it.
134   Write(file_name, {}, std::move(callback));
135 }
136 
137 }  // namespace chromeos