[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / cdm_service.cc
1 // Copyright 2014 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.
4
5 #include "media/mojo/services/cdm_service.h"
6
7 #include <utility>
8
9 #include "base/functional/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/memory/weak_ptr.h"
13 #include "media/base/cdm_factory.h"
14 #include "media/mojo/services/mojo_cdm_service.h"
15 #include "media/mojo/services/mojo_cdm_service_context.h"
16 #include "mojo/public/cpp/bindings/remote.h"
17 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
18
19 namespace media {
20
21 namespace {
22
23 // Implementation of mojom::CdmFactory that creates and hosts MojoCdmServices
24 // which then host CDMs created by the media::CdmFactory provided by the
25 // CdmService::Client.
26 //
27 // Lifetime Note:
28 // 1. CdmFactoryImpl instances are owned by a DeferredDestroyUniqueReceiverSet
29 //    directly, which is owned by CdmService.
30 // 2. CdmFactoryImpl is destroyed in any of the following two cases:
31 //   - CdmService is destroyed. Because of (2) this should not happen except for
32 //     during browser shutdown, when the Cdservice could be destroyed directly,
33 //     ignoring any outstanding interface connections.
34 //   - mojo::CdmFactory disconnection happens, AND CdmFactoryImpl doesn't own
35 //     any CDMs (|cdm_receivers_| is empty). This is to prevent destroying the
36 //     CDMs too early (e.g. during page navigation) which could cause errors
37 //     (session closed) on the client side. See https://crbug.com/821171 for
38 //     details.
39 class CdmFactoryImpl final : public DeferredDestroy<mojom::CdmFactory> {
40  public:
41   CdmFactoryImpl(CdmService::Client* client,
42                  mojo::PendingRemote<mojom::FrameInterfaceFactory> interfaces)
43       : client_(client), interfaces_(std::move(interfaces)) {
44     DVLOG(1) << __func__;
45
46     // base::Unretained is safe because |cdm_receivers_| is owned by |this|. If
47     // |this| is destructed, |cdm_receivers_| will be destructed as well and the
48     // error handler should never be called.
49     cdm_receivers_.set_disconnect_handler(base::BindRepeating(
50         &CdmFactoryImpl::OnReceiverDisconnect, base::Unretained(this)));
51   }
52
53   CdmFactoryImpl(const CdmFactoryImpl&) = delete;
54   CdmFactoryImpl operator=(const CdmFactoryImpl&) = delete;
55   ~CdmFactoryImpl() final { DVLOG(1) << __func__; }
56
57   // mojom::CdmFactory implementation.
58   void CreateCdm(const CdmConfig& cdm_config,
59                  CreateCdmCallback callback) final {
60     DVLOG(2) << __func__;
61
62     auto* cdm_factory = GetCdmFactory();
63     if (!cdm_factory) {
64       std::move(callback).Run(mojo::NullRemote(), nullptr,
65                               "CDM Factory creation failed");
66       return;
67     }
68
69     auto mojo_cdm_service =
70         std::make_unique<MojoCdmService>(&cdm_service_context_);
71     auto* raw_mojo_cdm_service = mojo_cdm_service.get();
72     DCHECK(!pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
73     pending_mojo_cdm_services_[raw_mojo_cdm_service] =
74         std::move(mojo_cdm_service);
75     raw_mojo_cdm_service->Initialize(
76         cdm_factory, cdm_config,
77         base::BindOnce(&CdmFactoryImpl::OnCdmServiceInitialized,
78                        weak_ptr_factory_.GetWeakPtr(), raw_mojo_cdm_service,
79                        std::move(callback)));
80   }
81
82   // DeferredDestroy<mojom::CdmFactory> implemenation.
83   void OnDestroyPending(base::OnceClosure destroy_cb) final {
84     destroy_cb_ = std::move(destroy_cb);
85     if (cdm_receivers_.empty())
86       std::move(destroy_cb_).Run();
87     // else the callback will be called when |cdm_receivers_| become empty.
88   }
89
90  private:
91   media::CdmFactory* GetCdmFactory() {
92     if (!cdm_factory_) {
93       cdm_factory_ = client_->CreateCdmFactory(interfaces_.get());
94       DLOG_IF(ERROR, !cdm_factory_) << "CdmFactory not available.";
95     }
96     return cdm_factory_.get();
97   }
98
99   void OnReceiverDisconnect() {
100     if (destroy_cb_ && cdm_receivers_.empty())
101       std::move(destroy_cb_).Run();
102   }
103
104   void OnCdmServiceInitialized(MojoCdmService* raw_mojo_cdm_service,
105                                CreateCdmCallback callback,
106                                mojom::CdmContextPtr cdm_context,
107                                const std::string& error_message) {
108     DCHECK(raw_mojo_cdm_service);
109
110     // Remove pending MojoCdmService from the mapping in all cases.
111     DCHECK(pending_mojo_cdm_services_.count(raw_mojo_cdm_service));
112     auto mojo_cdm_service =
113         std::move(pending_mojo_cdm_services_[raw_mojo_cdm_service]);
114     pending_mojo_cdm_services_.erase(raw_mojo_cdm_service);
115
116     if (!cdm_context) {
117       std::move(callback).Run(mojo::NullRemote(), nullptr, error_message);
118       return;
119     }
120
121     mojo::PendingRemote<mojom::ContentDecryptionModule> remote;
122     cdm_receivers_.Add(std::move(mojo_cdm_service),
123                        remote.InitWithNewPipeAndPassReceiver());
124     std::move(callback).Run(std::move(remote), std::move(cdm_context), "");
125   }
126
127   // Must be declared before the receivers below because the bound objects might
128   // take a raw pointer of |cdm_service_context_| and assume it's always
129   // available.
130   MojoCdmServiceContext cdm_service_context_;
131
132   raw_ptr<CdmService::Client> client_;
133   mojo::Remote<mojom::FrameInterfaceFactory> interfaces_;
134   mojo::UniqueReceiverSet<mojom::ContentDecryptionModule> cdm_receivers_;
135   std::unique_ptr<media::CdmFactory> cdm_factory_;
136   base::OnceClosure destroy_cb_;
137
138   // MojoCdmServices pending initialization.
139   std::map<MojoCdmService*, std::unique_ptr<MojoCdmService>>
140       pending_mojo_cdm_services_;
141
142   // NOTE: Weak pointers must be invalidated before all other member variables.
143   base::WeakPtrFactory<CdmFactoryImpl> weak_ptr_factory_{this};
144 };
145
146 }  // namespace
147
148 CdmService::CdmService(std::unique_ptr<Client> client,
149                        mojo::PendingReceiver<mojom::CdmService> receiver)
150     : receiver_(this, std::move(receiver)), client_(std::move(client)) {
151   DVLOG(1) << __func__;
152   DCHECK(client_);
153 }
154
155 CdmService::~CdmService() {
156   DVLOG(1) << __func__;
157 }
158
159 void CdmService::CreateCdmFactory(
160     mojo::PendingReceiver<mojom::CdmFactory> receiver,
161     mojo::PendingRemote<mojom::FrameInterfaceFactory> frame_interfaces) {
162   // Ignore receiver if service has already stopped.
163   if (!client_)
164     return;
165
166   cdm_factory_receivers_.Add(std::make_unique<CdmFactoryImpl>(
167                                  client_.get(), std::move(frame_interfaces)),
168                              std::move(receiver));
169 }
170
171 }  // namespace media