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