John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 1 | // Copyright 2017 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 | #ifndef CONTENT_BROWSER_MEDIA_CDM_FILE_IMPL_H_ |
| 6 | #define CONTENT_BROWSER_MEDIA_CDM_FILE_IMPL_H_ |
| 7 | |
| 8 | #include <string> |
John Rummell | 9fcfaa7 | 2019-06-13 23:08:12 | [diff] [blame] | 9 | #include <vector> |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 10 | |
| 11 | #include "base/callback_forward.h" |
| 12 | #include "base/files/file.h" |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 13 | #include "base/memory/ref_counted.h" |
| 14 | #include "base/memory/weak_ptr.h" |
John Rummell | 879f96f | 2019-07-25 07:32:14 | [diff] [blame] | 15 | #include "base/threading/sequence_bound.h" |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 16 | #include "base/threading/thread_checker.h" |
John Rummell | dc30ef53 | 2019-08-17 00:14:20 | [diff] [blame] | 17 | #include "base/time/time.h" |
Austin Sullivan | 22e0f3d | 2022-01-29 00:59:17 | [diff] [blame] | 18 | #include "media/cdm/cdm_type.h" |
Miyoung Shin | 25bb8c09 | 2019-08-03 00:56:57 | [diff] [blame] | 19 | #include "media/mojo/mojom/cdm_storage.mojom.h" |
Austin Sullivan | 5375575 | 2022-03-03 02:31:24 | [diff] [blame] | 20 | #include "mojo/public/cpp/bindings/associated_receiver.h" |
DongJun Kim | febb3c2 | 2019-10-21 02:08:06 | [diff] [blame] | 21 | #include "storage/browser/file_system/async_file_util.h" |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 22 | #include "url/origin.h" |
| 23 | |
| 24 | namespace storage { |
| 25 | class FileSystemContext; |
| 26 | class FileSystemURL; |
| 27 | } // namespace storage |
| 28 | |
| 29 | namespace content { |
Austin Sullivan | 5375575 | 2022-03-03 02:31:24 | [diff] [blame] | 30 | class MediaLicenseStorageHost; |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 31 | |
| 32 | // This class implements the media::mojom::CdmFile interface. It uses the same |
| 33 | // mojo pipe as CdmStorageImpl, to enforce message dispatch order. |
| 34 | class CdmFileImpl final : public media::mojom::CdmFile { |
| 35 | public: |
John Rummell | 9fcfaa7 | 2019-06-13 23:08:12 | [diff] [blame] | 36 | // Check whether |name| is valid as a usable file name. Returns true if it is, |
| 37 | // false otherwise. |
| 38 | static bool IsValidName(const std::string& name); |
| 39 | |
Austin Sullivan | 5375575 | 2022-03-03 02:31:24 | [diff] [blame] | 40 | // This "file" is actually just an entry in a custom backend for CDM, uniquely |
| 41 | // identified by a storage key, CDM type, and file name. File operations are |
| 42 | // routed through `host` which is owned by the storage partition. |
| 43 | CdmFileImpl( |
| 44 | MediaLicenseStorageHost* host, |
| 45 | const media::CdmType& cdm_type, |
| 46 | const std::string& file_name, |
| 47 | mojo::PendingAssociatedReceiver<media::mojom::CdmFile> pending_receiver); |
| 48 | |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 49 | CdmFileImpl(const std::string& file_name, |
| 50 | const url::Origin& origin, |
Austin Sullivan | 22e0f3d | 2022-01-29 00:59:17 | [diff] [blame] | 51 | const media::CdmType& cdm_type, |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 52 | const std::string& file_system_root_uri, |
| 53 | scoped_refptr<storage::FileSystemContext> file_system_context); |
Peter Boström | 828b902 | 2021-09-21 02:28:43 | [diff] [blame] | 54 | |
| 55 | CdmFileImpl(const CdmFileImpl&) = delete; |
| 56 | CdmFileImpl& operator=(const CdmFileImpl&) = delete; |
| 57 | |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 58 | ~CdmFileImpl() final; |
| 59 | |
John Rummell | 9fcfaa7 | 2019-06-13 23:08:12 | [diff] [blame] | 60 | // Called to grab a lock on the file. Returns false if the file is in use by |
| 61 | // other CDMs or by the system, true otherwise. Note that |this| should not |
| 62 | // be used anymore if Initialize() fails. |
| 63 | bool Initialize(); |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 64 | |
John Rummell | 9fcfaa7 | 2019-06-13 23:08:12 | [diff] [blame] | 65 | // media::mojom::CdmFile implementation. |
| 66 | void Read(ReadCallback callback) final; |
| 67 | void Write(const std::vector<uint8_t>& data, WriteCallback callback) final; |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 68 | |
| 69 | private: |
John Rummell | 137a6a5 | 2019-07-16 21:47:22 | [diff] [blame] | 70 | class FileReader; |
John Rummell | 879f96f | 2019-07-25 07:32:14 | [diff] [blame] | 71 | class FileWriter; |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 72 | |
John Rummell | 137a6a5 | 2019-07-16 21:47:22 | [diff] [blame] | 73 | // Called when the file is read. If |success| is true, |data| is the contents |
| 74 | // of the file read. |
| 75 | void ReadDone(bool success, std::vector<uint8_t> data); |
John Rummell | 9fcfaa7 | 2019-06-13 23:08:12 | [diff] [blame] | 76 | |
John Rummell | 879f96f | 2019-07-25 07:32:14 | [diff] [blame] | 77 | // Called in sequence to write the file. |buffer| is the contents to be |
| 78 | // written to the file, |bytes_to_write| is the length. Uses |file_writer_|, |
| 79 | // which is cleared when no longer needed. |write_callback_| will always be |
| 80 | // called with the result. |
John Rummell | 4894a80 | 2019-09-24 01:24:31 | [diff] [blame] | 81 | void OnEnsureTempFileExists(scoped_refptr<net::IOBuffer> buffer, |
| 82 | int bytes_to_write, |
| 83 | base::File::Error result, |
| 84 | bool created); |
| 85 | void OnTempFileIsEmpty(scoped_refptr<net::IOBuffer> buffer, |
| 86 | int bytes_to_write, |
| 87 | base::File::Error result); |
John Rummell | 879f96f | 2019-07-25 07:32:14 | [diff] [blame] | 88 | void WriteDone(bool success); |
| 89 | void OnFileRenamed(base::File::Error move_result); |
John Rummell | 9fcfaa7 | 2019-06-13 23:08:12 | [diff] [blame] | 90 | |
| 91 | // Deletes |file_name_| asynchronously. |
John Rummell | 879f96f | 2019-07-25 07:32:14 | [diff] [blame] | 92 | void DeleteFile(); |
| 93 | void OnFileDeleted(base::File::Error result); |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 94 | |
| 95 | // Returns the FileSystemURL for the specified |file_name|. |
| 96 | storage::FileSystemURL CreateFileSystemURL(const std::string& file_name); |
| 97 | |
| 98 | // Helper methods to lock and unlock a file. |
| 99 | bool AcquireFileLock(const std::string& file_name); |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 100 | void ReleaseFileLock(const std::string& file_name); |
| 101 | |
John Rummell | dc30ef53 | 2019-08-17 00:14:20 | [diff] [blame] | 102 | // Report operation time to UMA. |
| 103 | void ReportFileOperationTimeUMA(const std::string& uma_name); |
| 104 | |
Austin Sullivan | 5375575 | 2022-03-03 02:31:24 | [diff] [blame] | 105 | void ReadUsingMediaLicenseStorageDelegate(); |
| 106 | void DidReadUsingMediaLicenseStorageDelegate( |
| 107 | absl::optional<std::vector<uint8_t>> data); |
| 108 | void WriteUsingMediaLicenseStorageDelegate(const std::vector<uint8_t>& data); |
| 109 | void DidWriteUsingMediaLicenseStorageDelegate(bool success); |
| 110 | void DeleteUsingMediaLicenseStorageDelegate(); |
| 111 | void DidDeleteUsingMediaLicenseStorageDelegate(bool success); |
| 112 | |
| 113 | void OnReceiverDisconnect(); |
| 114 | |
| 115 | // This receiver is associated with the CdmStorage receiver which creates it. |
| 116 | mojo::AssociatedReceiver<media::mojom::CdmFile> receiver_{this}; |
| 117 | |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 118 | // Names of the files this class represents. |
| 119 | const std::string file_name_; |
| 120 | const std::string temp_file_name_; |
| 121 | |
Austin Sullivan | 1fd0781 | 2021-12-15 02:43:28 | [diff] [blame] | 122 | // TODO(crbug.com/1231162): Remove some of these fields and update this |
| 123 | // comment when we migrate off of the PluginPrivateFileSystem. |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 124 | // Files are stored in the PluginPrivateFileSystem. The following are needed |
| 125 | // to access files. |
| 126 | const url::Origin origin_; |
Austin Sullivan | 22e0f3d | 2022-01-29 00:59:17 | [diff] [blame] | 127 | const media::CdmType cdm_type_; |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 128 | const std::string file_system_root_uri_; |
| 129 | scoped_refptr<storage::FileSystemContext> file_system_context_; |
| 130 | |
John Rummell | 9fcfaa7 | 2019-06-13 23:08:12 | [diff] [blame] | 131 | // Keep track of when the original file |file_name_| is locked. |
| 132 | // Initialize() can only be called if false and takes the lock (on success). |
| 133 | // Read() and Write() can only be called if true. |
| 134 | // Note that having a lock on |file_name| implies that |temp_file_name| is |
| 135 | // reserved for use by this object only, and an explicit lock on |
| 136 | // |temp_file_name| is not required. |
| 137 | bool file_locked_ = false; |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 138 | |
John Rummell | 137a6a5 | 2019-07-16 21:47:22 | [diff] [blame] | 139 | // Used when reading the file. |file_reader_| lives on the IO thread. |
| 140 | ReadCallback read_callback_; |
John Rummell | 879f96f | 2019-07-25 07:32:14 | [diff] [blame] | 141 | base::SequenceBound<FileReader> file_reader_; |
| 142 | |
| 143 | // Used when writing the file. |file_writer_| lives on the IO thread. |
| 144 | WriteCallback write_callback_; |
| 145 | base::SequenceBound<FileWriter> file_writer_; |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 146 | |
John Rummell | dc30ef53 | 2019-08-17 00:14:20 | [diff] [blame] | 147 | // Time when the read or write operation starts. |
| 148 | base::TimeTicks start_time_; |
| 149 | |
Austin Sullivan | 5375575 | 2022-03-03 02:31:24 | [diff] [blame] | 150 | // Backing store which CDM file operations are routed through. |
| 151 | // Owned by MediaLicenseManager. |
| 152 | const raw_ptr<MediaLicenseStorageHost> host_ = nullptr; |
| 153 | |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 154 | THREAD_CHECKER(thread_checker_); |
Jeremy Roman | 3bca4bf | 2019-07-11 03:41:25 | [diff] [blame] | 155 | base::WeakPtrFactory<CdmFileImpl> weak_factory_{this}; |
John Rummell | aa05b9c | 2017-10-30 08:41:29 | [diff] [blame] | 156 | }; |
| 157 | |
| 158 | } // namespace content |
| 159 | |
| 160 | #endif // CONTENT_BROWSER_MEDIA_CDM_FILE_IMPL_H_ |