Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "GMPContentParent.h"
7 : #include "GMPDecryptorParent.h"
8 : #include "GMPParent.h"
9 : #include "GMPServiceChild.h"
10 : #include "GMPVideoDecoderParent.h"
11 : #include "GMPVideoEncoderParent.h"
12 : #include "ChromiumCDMParent.h"
13 : #include "mozIGeckoMediaPluginService.h"
14 : #include "mozilla/Logging.h"
15 : #include "mozilla/Unused.h"
16 : #include "base/task.h"
17 :
18 : namespace mozilla {
19 :
20 : #ifdef LOG
21 : #undef LOG
22 : #endif
23 :
24 : extern LogModule* GetGMPLog();
25 :
26 : #define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
27 : #define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg)
28 :
29 : #ifdef __CLASS__
30 : #undef __CLASS__
31 : #endif
32 : #define __CLASS__ "GMPContentParent"
33 :
34 : namespace gmp {
35 :
36 0 : GMPContentParent::GMPContentParent(GMPParent* aParent)
37 0 : : mParent(aParent)
38 : {
39 0 : if (mParent) {
40 0 : SetDisplayName(mParent->GetDisplayName());
41 0 : SetPluginId(mParent->GetPluginId());
42 : }
43 0 : }
44 :
45 0 : GMPContentParent::~GMPContentParent()
46 : {
47 0 : }
48 :
49 0 : class ReleaseGMPContentParent : public Runnable
50 : {
51 : public:
52 0 : explicit ReleaseGMPContentParent(GMPContentParent* aToRelease)
53 0 : : Runnable("gmp::ReleaseGMPContentParent")
54 0 : , mToRelease(aToRelease)
55 : {
56 0 : }
57 :
58 0 : NS_IMETHOD Run() override
59 : {
60 0 : return NS_OK;
61 : }
62 :
63 : private:
64 : RefPtr<GMPContentParent> mToRelease;
65 : };
66 :
67 : void
68 0 : GMPContentParent::ActorDestroy(ActorDestroyReason aWhy)
69 : {
70 0 : MOZ_ASSERT(mDecryptors.IsEmpty() && mVideoDecoders.IsEmpty() &&
71 : mVideoEncoders.IsEmpty() && mChromiumCDMs.IsEmpty());
72 0 : NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this));
73 0 : }
74 :
75 : void
76 0 : GMPContentParent::CheckThread()
77 : {
78 0 : MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
79 0 : }
80 :
81 : void
82 0 : GMPContentParent::ChromiumCDMDestroyed(ChromiumCDMParent* aDecoder)
83 : {
84 0 : MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
85 :
86 0 : MOZ_ALWAYS_TRUE(mChromiumCDMs.RemoveElement(aDecoder));
87 0 : CloseIfUnused();
88 0 : }
89 :
90 : void
91 0 : GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
92 : {
93 0 : MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
94 :
95 : // If the constructor fails, we'll get called before it's added
96 0 : Unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder));
97 0 : CloseIfUnused();
98 0 : }
99 :
100 : void
101 0 : GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder)
102 : {
103 0 : MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
104 :
105 : // If the constructor fails, we'll get called before it's added
106 0 : Unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder));
107 0 : CloseIfUnused();
108 0 : }
109 :
110 : void
111 0 : GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
112 : {
113 0 : MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
114 :
115 0 : MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession));
116 0 : CloseIfUnused();
117 0 : }
118 :
119 : void
120 0 : GMPContentParent::AddCloseBlocker()
121 : {
122 0 : MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
123 0 : ++mCloseBlockerCount;
124 0 : }
125 :
126 : void
127 0 : GMPContentParent::RemoveCloseBlocker()
128 : {
129 0 : MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
130 0 : --mCloseBlockerCount;
131 0 : CloseIfUnused();
132 0 : }
133 :
134 : void
135 0 : GMPContentParent::CloseIfUnused()
136 : {
137 0 : if (mDecryptors.IsEmpty() && mVideoDecoders.IsEmpty() &&
138 0 : mVideoEncoders.IsEmpty() && mChromiumCDMs.IsEmpty() &&
139 0 : mCloseBlockerCount == 0) {
140 0 : RefPtr<GMPContentParent> toClose;
141 0 : if (mParent) {
142 0 : toClose = mParent->ForgetGMPContentParent();
143 : } else {
144 0 : toClose = this;
145 : RefPtr<GeckoMediaPluginServiceChild> gmp(
146 0 : GeckoMediaPluginServiceChild::GetSingleton());
147 0 : gmp->RemoveGMPContentParent(toClose);
148 : }
149 0 : NS_DispatchToCurrentThread(NewRunnableMethod(
150 0 : "gmp::GMPContentParent::Close", toClose, &GMPContentParent::Close));
151 : }
152 0 : }
153 :
154 : nsresult
155 0 : GMPContentParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP)
156 : {
157 0 : PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor();
158 0 : if (!pdp) {
159 0 : return NS_ERROR_FAILURE;
160 : }
161 0 : GMPDecryptorParent* dp = static_cast<GMPDecryptorParent*>(pdp);
162 : // This addref corresponds to the Proxy pointer the consumer is returned.
163 : // It's dropped by calling Close() on the interface.
164 0 : NS_ADDREF(dp);
165 0 : mDecryptors.AppendElement(dp);
166 0 : *aGMPDP = dp;
167 :
168 0 : return NS_OK;
169 : }
170 :
171 : nsCOMPtr<nsISerialEventTarget>
172 0 : GMPContentParent::GMPEventTarget()
173 : {
174 0 : if (!mGMPEventTarget) {
175 0 : nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
176 0 : MOZ_ASSERT(mps);
177 0 : if (!mps) {
178 0 : return nullptr;
179 : }
180 : // Not really safe if we just grab to the mGMPEventTarget, as we don't know
181 : // what thread we're running on and other threads may be trying to
182 : // access this without locks! However, debug only, and primary failure
183 : // mode outside of compiler-helped TSAN is a leak. But better would be
184 : // to use swap() under a lock.
185 0 : nsCOMPtr<nsIThread> gmpThread;
186 0 : mps->GetThread(getter_AddRefs(gmpThread));
187 0 : MOZ_ASSERT(gmpThread);
188 :
189 0 : mGMPEventTarget = gmpThread->SerialEventTarget();
190 : }
191 :
192 0 : return mGMPEventTarget;
193 : }
194 :
195 : already_AddRefed<ChromiumCDMParent>
196 0 : GMPContentParent::GetChromiumCDM()
197 : {
198 0 : PChromiumCDMParent* actor = SendPChromiumCDMConstructor();
199 0 : if (!actor) {
200 0 : return nullptr;
201 : }
202 0 : RefPtr<ChromiumCDMParent> parent = static_cast<ChromiumCDMParent*>(actor);
203 :
204 : // TODO: Remove parent from mChromiumCDMs in ChromiumCDMParent::Destroy().
205 0 : mChromiumCDMs.AppendElement(parent);
206 :
207 0 : return parent.forget();
208 : }
209 :
210 : nsresult
211 0 : GMPContentParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD,
212 : uint32_t aDecryptorId)
213 : {
214 : // returned with one anonymous AddRef that locks it until Destroy
215 0 : PGMPVideoDecoderParent* pvdp = SendPGMPVideoDecoderConstructor(aDecryptorId);
216 0 : if (!pvdp) {
217 0 : return NS_ERROR_FAILURE;
218 : }
219 0 : GMPVideoDecoderParent *vdp = static_cast<GMPVideoDecoderParent*>(pvdp);
220 : // This addref corresponds to the Proxy pointer the consumer is returned.
221 : // It's dropped by calling Close() on the interface.
222 0 : NS_ADDREF(vdp);
223 0 : *aGMPVD = vdp;
224 0 : mVideoDecoders.AppendElement(vdp);
225 :
226 0 : return NS_OK;
227 : }
228 :
229 : nsresult
230 0 : GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE)
231 : {
232 : // returned with one anonymous AddRef that locks it until Destroy
233 0 : PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor();
234 0 : if (!pvep) {
235 0 : return NS_ERROR_FAILURE;
236 : }
237 0 : GMPVideoEncoderParent *vep = static_cast<GMPVideoEncoderParent*>(pvep);
238 : // This addref corresponds to the Proxy pointer the consumer is returned.
239 : // It's dropped by calling Close() on the interface.
240 0 : NS_ADDREF(vep);
241 0 : *aGMPVE = vep;
242 0 : mVideoEncoders.AppendElement(vep);
243 :
244 0 : return NS_OK;
245 : }
246 :
247 : PChromiumCDMParent*
248 0 : GMPContentParent::AllocPChromiumCDMParent()
249 : {
250 0 : ChromiumCDMParent* parent = new ChromiumCDMParent(this, GetPluginId());
251 0 : NS_ADDREF(parent);
252 0 : return parent;
253 : }
254 :
255 : PGMPVideoDecoderParent*
256 0 : GMPContentParent::AllocPGMPVideoDecoderParent(const uint32_t& aDecryptorId)
257 : {
258 0 : GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this);
259 0 : NS_ADDREF(vdp);
260 0 : return vdp;
261 : }
262 :
263 : bool
264 0 : GMPContentParent::DeallocPChromiumCDMParent(PChromiumCDMParent* aActor)
265 : {
266 0 : ChromiumCDMParent* parent = static_cast<ChromiumCDMParent*>(aActor);
267 0 : NS_RELEASE(parent);
268 0 : return true;
269 : }
270 :
271 : bool
272 0 : GMPContentParent::DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor)
273 : {
274 0 : GMPVideoDecoderParent* vdp = static_cast<GMPVideoDecoderParent*>(aActor);
275 0 : NS_RELEASE(vdp);
276 0 : return true;
277 : }
278 :
279 : PGMPVideoEncoderParent*
280 0 : GMPContentParent::AllocPGMPVideoEncoderParent()
281 : {
282 0 : GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this);
283 0 : NS_ADDREF(vep);
284 0 : return vep;
285 : }
286 :
287 : bool
288 0 : GMPContentParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor)
289 : {
290 0 : GMPVideoEncoderParent* vep = static_cast<GMPVideoEncoderParent*>(aActor);
291 0 : NS_RELEASE(vep);
292 0 : return true;
293 : }
294 :
295 : PGMPDecryptorParent*
296 0 : GMPContentParent::AllocPGMPDecryptorParent()
297 : {
298 0 : GMPDecryptorParent* ksp = new GMPDecryptorParent(this);
299 0 : NS_ADDREF(ksp);
300 0 : return ksp;
301 : }
302 :
303 : bool
304 0 : GMPContentParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor)
305 : {
306 0 : GMPDecryptorParent* ksp = static_cast<GMPDecryptorParent*>(aActor);
307 0 : NS_RELEASE(ksp);
308 0 : return true;
309 : }
310 :
311 : } // namespace gmp
312 : } // namespace mozilla
|